Phát hiện nếu giá trị là số trong MySQL


159

Có cách nào để phát hiện nếu một giá trị là một số trong truy vấn MySQL không? Nhu la

SELECT * 
FROM myTable 
WHERE isANumber(col1) = true

Tôi đã thử nghiệm chiến lược 1 * col = col, nhưng bằng cách nào đó, nó thất bại khi truy vấn được gọi thông qua PHP (trả về đúng khi không nên tấn công). Tuy nhiên, trong phpMyAdmin, hack hoạt động. Điều này có nghĩa là bài kiểm tra của tôi hoạt động như mong đợi, hãy mua ứng dụng của tôi không.
Jahaziel

Câu trả lời:


249

Điều này sẽ làm việc trong hầu hết các trường hợp.

SELECT * FROM myTable WHERE concat('',col1 * 1) = col1

Nó không hoạt động đối với các số không chuẩn như

  • 1e4
  • 1.2e5
  • 123. (dấu thập phân)

Cảm ơn bạn. Thật không may, tôi cần nó để nhận ra rằng 123 là một số, nhưng 123X thì không.
Urbycoz

1
@ Richard- Tôi chỉ đọc những ngoại lệ bạn đưa ra. Nghĩ rằng bạn có nghĩa là nhân vật "e". Tôi thấy những gì bạn có nghĩa là bây giờ.
Urbycoz

Các số 0 đứng đầu không phải là vấn đề đối với nhà phát triển sql khéo léo --- trim (dẫn 0 từ col1)
pimbrouwers

Tôi biết đó là một bài viết cũ nhưng tôi sử dụng phương pháp này trong truy vấn của mình. Nhưng tôi có một vấn đề, nó phát hiện "2-Power" là "2" gây rắc rối vì nó không phải làm điều đó. Bất kỳ ý tưởng ?
GRosay

1
Đối với các số 0 ở đầu và cuối (ví dụ 023.12000): concat ('', col1 * 1) = '0' OR concat ('', col1 * 1) = IF (LOCATE ('.', Col1), TRIM (BÓNG ' 0 'TỪ col1), TRIM (HÀNG ĐẦU' 0 'TỪ col1));
François Breton

298

Bạn cũng có thể sử dụng Biểu thức chính quy ... nó sẽ giống như:

SELECT * FROM myTable WHERE col1 REGEXP '^[0-9]+$';

Tham khảo: http://dev.mysql.com/doc/refman/5.1/en/regapi.html


70
CHỌN * TỪ myTable WHERE col1 REGEXP '^ [0-9] + $';
Dmitriy Kozmenko

6
Câu trả lời được chấp nhận là thực sự thông minh, nhưng câu trả lời này trực tiếp hơn, và tôi nghĩ nó nên là giải pháp được chấp nhận.
pedromanoel

21
Đối với trường hợp "không khớp": WHERE col1 NOT REGEXP...và đối với trường hợp bạn có thể có dấu thập phân, hãy sử dụng regex:^[0-9\.]+$
Robbie Averill

2
Cũng sẽ không hoạt động cho ký hiệu khoa học, chỉ hoạt động cho ints
David Wilkins

1
Regex Migth rất khó đọc đối với những người không bao giờ sử dụng nó, nhưng bạn có thể làm những điều thực sự tuyệt vời và ngắn với nó
Olli

56

Nếu dữ liệu của bạn là 'test', 'test0', 'test1111', '111test', '111'

Để chọn tất cả các bản ghi trong đó dữ liệu là một int đơn giản:

SELECT * 
FROM myTable 
WHERE col1 REGEXP '^[0-9]+$';

Kết quả: '111'

(Trong regex, ^ có nghĩa là bắt đầu và $ có nghĩa là kết thúc)

Để chọn tất cả các bản ghi có số nguyên hoặc số thập phân tồn tại:

SELECT * 
FROM myTable 
WHERE col1 REGEXP '^[0-9]+\\.?[0-9]*$'; - for 123.12

Kết quả: '111' (giống như ví dụ trước)

Cuối cùng, để chọn tất cả các bản ghi nơi số tồn tại, sử dụng:

SELECT * 
FROM myTable 
WHERE col1 REGEXP '[0-9]+';

Kết quả: 'test0' và 'test1111' và '111test' và '111'


Tôi thích cách tiếp cận này tốt hơn vì nó rõ ràng hơn và ít "hackish" hơn so với thủ thuật ghép nối. Cảm ơn!
brokethebuildagain

8
Không làm việc cho các giá trị âm. Tôi sẽ sửa đổi biểu thức chính quy được đề xuất như sau:REGEXP '^[+\-]?[0-9]+\\.?[0-9]*$'
Nicolas

Tôi muốn nói biểu tượng "+" là không cần thiết, bạn có thể chỉ sử dụng dấu "-?", Nhưng nếu bạn muốn sử dụng nó, bạn nên thoát nó (và biểu tượng "-" không cần phải thoát) .
T. Góc

13
SELECT * FROM myTable
WHERE col1 REGEXP '^[+-]?[0-9]*([0-9]\\.|[0-9]|\\.[0-9])[0-9]*(e[+-]?[0-9]+)?$'

Cũng sẽ khớp các số thập phân đã ký (như -1.2, +0.2, 6., 2e9, 1.2e-10 ).

Kiểm tra:

drop table if exists myTable;
create table myTable (col1 varchar(50));
insert into myTable (col1) 
  values ('00.00'),('+1'),('.123'),('-.23e4'),('12.e-5'),('3.5e+6'),('a'),('e6'),('+e0');

select 
  col1,
  col1 + 0 as casted,
  col1 REGEXP '^[+-]?[0-9]*([0-9]\\.|[0-9]|\\.[0-9])[0-9]*(e[+-]?[0-9]+)?$' as isNumeric
from myTable;

Kết quả:

col1   |  casted | isNumeric
-------|---------|----------
00.00  |       0 |         1
+1     |       1 |         1
.123   |   0.123 |         1
-.23e4 |   -2300 |         1
12.e-5 | 0.00012 |         1
3.5e+6 | 3500000 |         1
a      |       0 |         0
e6     |       0 |         0
+e0    |       0 |         0

Bản giới thiệu


3
Hoàn hảo! Chỉ trả lời mà thực sự bao gồm tất cả các cơ sở. Nên là câu trả lời được chấp nhận.
Dom

10

Trả về các hàng số

Tôi tìm thấy giải pháp với truy vấn sau và làm việc cho tôi:

SELECT * FROM myTable WHERE col1 > 0;

Truy vấn này trả về các hàng chỉ có cột số lớn hơn 0 col1

Trả về các hàng không số

nếu bạn muốn kiểm tra cột không phải là số, hãy thử cột này với mẹo ( !col1 > 0):

SELECT * FROM myTable WHERE !col1 > 0;

Điều này không hoạt động, nếu bạn có một chuỗi bắt đầu bằng số "123abc", nó sẽ được trả về trong câu lệnh hàng số của bạn chứ không phải trong câu lệnh không phải là số.
JStephen

@JStephen Bạn đúng! Bởi vì SELECT * FROM myTable WHERE col1 = 123;truy vấn sẽ trả về các hàng thậm chí giá trị col là123abc
Bora

9

Câu trả lời này tương tự như Dmitry, nhưng nó sẽ cho phép các số thập phân cũng như các số dương và âm.

select * from table where col1 REGEXP '^[[:digit:]]+$'

8

sử dụng UDF (chức năng do người dùng xác định).

CREATE FUNCTION isnumber(inputValue VARCHAR(50))
  RETURNS INT
  BEGIN
    IF (inputValue REGEXP ('^[0-9]+$'))
    THEN
      RETURN 1;
    ELSE
      RETURN 0;
    END IF;
  END;

Sau đó khi bạn truy vấn

select isnumber('383XXXX') 

- trả lại 0

select isnumber('38333434') 

- trả lại 1

chọn isnumber (mycol) mycol1, col2, colx từ bảngx; - sẽ trả về 1s và 0 cho cột mycol1

- bạn có thể tăng cường chức năng để lấy số thập phân, ký hiệu khoa học, v.v ...

Ưu điểm của việc sử dụng UDF là bạn có thể sử dụng nó ở bên trái hoặc bên phải của phép so sánh "mệnh đề where" của bạn. điều này giúp đơn giản hóa rất nhiều SQL của bạn trước khi được gửi đến cơ sở dữ liệu:

 SELECT * from tablex where isnumber(columnX) = isnumber('UnkownUserInput');

hi vọng điêu nay co ich.


5

Một cách khác có vẻ nhanh hơn REGEXP trên máy tính của tôi là

SELECT * FROM myTable WHERE col1*0 != col1;

Điều này sẽ chọn tất cả các hàng trong đó col1 bắt đầu bằng một giá trị số.


2
Nếu giá trị bằng 0 thì sao?
Urbycoz

1
Tôi đoán bạn chỉ có thể thêm AND col1<>0để xử lý ngoại lệ đó.
Urbycoz

Đúng là nó không hoạt động với các giá trị 0 nhưng nó hoạt động hoàn hảo cho các số được đệm, ví dụ 004. Câu trả lời được chấp nhận không hoạt động đối với các số được đệm
Abbas

Tôi nghĩ rằng đây là cách tốt nhất để kiểm tra số lượng. Chỉ là chúng ta cần thêm một câu lệnh OR để kiểm tra số 0, vì CHỌN * TỪ myTable WHERE col1 * 0! = Col1 OR col1 = '0';
Binu Raman

Tôi nhận được một dương tính giả cho '1a'. BTW: nó tương đương với WHERE col1 <> 0- rextester.com/DJIS1493
Paul Spiegel

4

Vẫn còn thiếu phiên bản đơn giản này:

SELECT * FROM myTable WHERE `col1` + 0 = `col1`

(bổ sung nên nhanh hơn khi nhân)

Hoặc phiên bản chậm nhất để chơi tiếp:

SELECT *, 
CASE WHEN `col1` + 0 = `col1` THEN 1 ELSE 0 END AS `IS_NUMERIC` 
FROM `myTable`
HAVING `IS_NUMERIC` = 1

3
Trừ khi tôi hiểu nhầm, MySQL chuyển đổi bất kỳ chuỗi nào thành 0 nên điều này sẽ không phân biệt giữa chuỗi và số, cả hai sẽ trả về như nhau.
Ivan McA

3
'a' + 0 = 'a'là TRUE
Paul Spiegel

3

Tôi khuyên bạn: nếu tìm kiếm của bạn đơn giản, bạn có thể sử dụng `

column*1 = column

`Toán tử thú vị :) là công việc và nhanh hơn trên các trường varchar / char

CHỌN * TỪ cột myTable WHERE * 1 = cột;

ABC*1 => 0 (NOT EQU **ABC**)
AB15*A => 15 (NOT EQU **AB15**)
15AB => 15 (NOT EQU **15AB**)
15 => 15 (EQUALS TRUE **15**)

1
Bạn có biết rằng trong MySQL cả select 'aaa123' >= 0select '123aaa' >= 0trả về đúng không?
Grzegorz Smulko

1
SELECT * FROM myTable WHERE sign (col1)!=0

dấu hiệu (0) bằng 0, nhưng sau đó bạn có thể hạn chế truy vấn của mình để ...

SELECT * FROM myTable WHERE sign (col1)!=0 or col1=0

CẬP NHẬT: Điều này không đáng tin cậy 100%, vì "1abc" sẽ trả về dấu 1, nhưng "ab1c" sẽ trả về 0 ... vì vậy điều này chỉ có thể hoạt động đối với văn bản không bắt đầu bằng số.


0

bạn có thể làm bằng cách sử dụng CAST

  SELECT * from tbl where col1 = concat(cast(col1 as decimal), "")


-1

Hãy thử Chia / 1

select if(value/1>0 or value=0,'its a number', 'its not a number') from table
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.