Làm cách nào để kiểm tra xem một giá trị có phải là số nguyên trong MySQL hay không?


123

Tôi thấy rằng trong MySQL có Cast()và các Convert()hàm tạo số nguyên từ các giá trị, nhưng có cách nào để kiểm tra xem một giá trị có phải là số nguyên không? Một cái gì đó giống như is_int()trong PHP là những gì tôi đang tìm kiếm.


2
nên buồn bã chúng ta phải tạo is_int () chức năng trong Mysql
Yuda Prawira

Câu trả lời:


214

Tôi giả sử bạn muốn kiểm tra một giá trị chuỗi. Một cách hay là toán tử REGEXP, khớp chuỗi với một biểu thức chính quy. Đơn giản là làm

select field from table where field REGEXP '^-?[0-9]+$';

điều này khá nhanh. Nếu trường của bạn là số, chỉ cần kiểm tra

ceil(field) = field

thay thế.


4
Kiểm tra 'ceil (field) = field' là một ý tưởng hay, nhưng như @Jumpy đã chỉ ra, nó không thành công trên dữ liệu không phải là số: SELECT ceil ('four') = 'four'; -> 1
Matthew Cornell

3
@MatthewCornell, Anh ấy nói nếu trường của bạn là số. Vì vậy, bạn có thể kiểm tra xem một số có phải là số nguyên hay không. Nó sẽ không hoạt động trên chuỗi, đó là lý do tại sao tùy chọn đầu tiên ở đó.
Malfist

Nếu dữ liệu có thể bao gồm khoảng trắng, điều này sẽ không thành công. Cân nhắc thử nghiệm trim (trường), có thể có thêm đối số để loại bỏ các dòng mới.
Michael Grazebrook

dữ liệu là số, cũng có thể thực hiện điều này: select ((field% 1) = 0);
ThiamTeck

Cảm ơn, nhưng đối với việc so sánh số, tôi nghĩ rằng bạn không cần (strcmp (ceil (lĩnh vực), lĩnh vực))
Alan Dixon

14

So khớp nó với một biểu thức chính quy.

cf http://forums.mysql.com/read.php?60,1907,38488#msg-38488 như được trích dẫn bên dưới:

Re: Mệnh đề IsNumeric () trong MySQL ??
Đăng bởi: kevinclark ()
Ngày: 08 tháng 8 năm 2005 01:01 PM


Tôi đồng ý. Đây là một hàm tôi đã tạo cho MySQL 5:

CREATE FUNCTION IsNumeric (sIn varchar(1024)) RETURNS tinyint
RETURN sIn REGEXP '^(-|\\+){0,1}([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+|[0-9]+)$';


Điều này cho phép một dấu cộng / trừ tùy chọn ở đầu, một dấu thập phân tùy chọn và các chữ số số còn lại.


Cảm ơn, giải pháp của bạn sẽ chăm sóc của số thập phân cũng
Ananda

12

Giả sử chúng ta có cột với trường chữ và số có các mục nhập như

a41q
1458
xwe8
1475
asde
9582
.
.
.
.
.
qe84

và bạn muốn giá trị số cao nhất từ ​​cột db này (trong trường hợp này là 9582) thì truy vấn này sẽ giúp bạn

SELECT Max(column_name) from table_name where column_name REGEXP '^[0-9]+$'

1
'10000' cao hơn, nhưng truy vấn của bạn sẽ vẫn trả về '9582' .
Paul Spiegel

8

Đây là giải pháp đơn giản cho nó giả sử kiểu dữ liệu là varchar

select * from calender where year > 0

Nó sẽ trả về true nếu năm là số khác false


29
Trong một varchar, điều này cũng sẽ trả về true nếu ký tự đầu tiên là số.
TuK

Không nhận thấy điều đó. bỏ phiếu bình luận của bạn :)
Jayjitraj

8

Điều này cũng hoạt động:

CAST( coulmn_value AS UNSIGNED ) // will return 0 if not numeric string.

ví dụ

SELECT CAST('a123' AS UNSIGNED) // returns 0
SELECT CAST('123' AS UNSIGNED) // returns 123 i.e. > 0

11
những gì về SELECT CAST('12a34' AS UNSIGNED), những gì trả lại 12?
Mike C

1
Điều này hoạt động hoàn hảo nếu bạn cần kiểm tra các mục không phải là số, điều này xứng đáng được +1. Các câu trả lời khác khó hơn để đảo ngược bài kiểm tra để tìm các mục không phải là số.
DrCord

1
@DrCord điều này không hoạt động đối với trường hợp Mike C đã mô tả, do đó rất không đáng tin cậy
jontro

4

Để kiểm tra xem một giá trị có phải là Int trong Mysql hay không, chúng ta có thể sử dụng truy vấn sau. Truy vấn này sẽ cung cấp cho các hàng có giá trị Int

SELECT col1 FROM table WHERE concat('',col * 1) = col;

Thao tác này cũng sẽ chọn các số không phải số nguyên (ví dụ: '3.5' ).
Paul Spiegel

4

Điều tốt nhất tôi có thể nghĩ về một biến là một int Là sự kết hợp với các chức năng của MySQL CAST()LENGTH().
Phương thức này sẽ hoạt động trên các kiểu dữ liệu chuỗi, số nguyên, double / float.

SELECT (LENGTH(CAST(<data> AS UNSIGNED))) = (LENGTH(<data>)) AS is_int

xem bản demo http://sqlfiddle.com/#!9/ff40cd/44

nó sẽ không thành công nếu cột có một giá trị ký tự duy nhất. nếu cột có giá trị 'A' thì Cast ('A' là UNSIGNED) sẽ đánh giá là 0 và LENGTH (0) sẽ là 1. vì vậy LENGTH (Cast ('A' as UNSIGNED)) = LENGTH (0) sẽ đánh giá là 1 = 1 => 1

True Waqas Malik hoàn toàn mù mờ để kiểm tra trường hợp đó. bản vá là.

SELECT <data>, (LENGTH(CAST(<data> AS UNSIGNED))) = CASE WHEN CAST(<data> AS UNSIGNED) = 0 THEN CAST(<data> AS UNSIGNED) ELSE (LENGTH(<data>)) END AS is_int;

Các kết quả

**Query #1**

    SELECT 1, (LENGTH(CAST(1 AS UNSIGNED))) = CASE WHEN CAST(1 AS UNSIGNED) = 0 THEN CAST(1 AS UNSIGNED) ELSE (LENGTH(1)) END AS is_int;

| 1   | is_int |
| --- | ------ |
| 1   | 1      |

---
**Query #2**

    SELECT 1.1, (LENGTH(CAST(1 AS UNSIGNED))) = CASE WHEN CAST(1.1 AS UNSIGNED) = 0 THEN CAST(1.1 AS UNSIGNED) ELSE (LENGTH(1.1)) END AS is_int;

| 1.1 | is_int |
| --- | ------ |
| 1.1 | 0      |

---
**Query #3**

    SELECT "1", (LENGTH(CAST("1" AS UNSIGNED))) = CASE WHEN CAST("1" AS UNSIGNED) = 0 THEN CAST("1" AS UNSIGNED) ELSE (LENGTH("1")) END AS is_int;

| 1   | is_int |
| --- | ------ |
| 1   | 1      |

---
**Query #4**

    SELECT "1.1", (LENGTH(CAST("1.1" AS UNSIGNED))) = CASE WHEN CAST("1.1" AS UNSIGNED) = 0 THEN CAST("1.1" AS UNSIGNED) ELSE (LENGTH("1.1")) END AS is_int;

| 1.1 | is_int |
| --- | ------ |
| 1.1 | 0      |

---
**Query #5**

    SELECT "1a", (LENGTH(CAST("1.1" AS UNSIGNED))) = CASE WHEN CAST("1a" AS UNSIGNED) = 0 THEN CAST("1a" AS UNSIGNED) ELSE (LENGTH("1a")) END AS is_int;

| 1a  | is_int |
| --- | ------ |
| 1a  | 0      |

---
**Query #6**

    SELECT "1.1a", (LENGTH(CAST("1.1a" AS UNSIGNED))) = CASE WHEN CAST("1.1a" AS UNSIGNED) = 0 THEN CAST("1.1a" AS UNSIGNED) ELSE (LENGTH("1.1a")) END AS is_int;

| 1.1a | is_int |
| ---- | ------ |
| 1.1a | 0      |

---
**Query #7**

    SELECT "a1", (LENGTH(CAST("1.1a" AS UNSIGNED))) = CASE WHEN CAST("a1" AS UNSIGNED) = 0 THEN CAST("a1" AS UNSIGNED) ELSE (LENGTH("a1")) END AS is_int;

| a1  | is_int |
| --- | ------ |
| a1  | 0      |

---
**Query #8**

    SELECT "a1.1", (LENGTH(CAST("a1.1" AS UNSIGNED))) = CASE WHEN CAST("a1.1" AS UNSIGNED) = 0 THEN CAST("a1.1" AS UNSIGNED) ELSE (LENGTH("a1.1")) END AS is_int;

| a1.1 | is_int |
| ---- | ------ |
| a1.1 | 0      |

---
**Query #9**

    SELECT "a", (LENGTH(CAST("a" AS UNSIGNED))) = CASE WHEN CAST("a" AS UNSIGNED) = 0 THEN CAST("a" AS UNSIGNED) ELSE (LENGTH("a")) END AS is_int;

| a   | is_int |
| --- | ------ |
| a   | 0      |

xem demo


nó sẽ không thành công nếu cột có một giá trị ký tự duy nhất. nếu cột có giá trị 'A' thì Cast ('A' là UNSIGNED) sẽ đánh giá là 0 và LENGTH (0) sẽ là 1. vì vậy LENGTH (Cast ('A' as UNSIGNED)) = LENGTH (0) sẽ đánh giá là 1 = 1 => 1
Waqas Malik

Cảm ơn đã bình luận rằng trường hợp đã thực sự chưa được kiểm tra @WaqasMalik làm việc và thử nghiệm một bản vá ngay bây giờ .. cái gì đó nhưSELECT "a", (LENGTH(CAST("a" AS UNSIGNED))) = CASE WHEN CAST("a" AS UNSIGNED) = 0 THEN CAST("a" AS UNSIGNED) ELSE (LENGTH("a")) END AS is_int;
Raymond Nijland

Đây là một giải pháp mát mẻ. Tôi nghĩ rằng nó không thành công với số nguyên âm, nó có thay đổi bất kỳ điều gì đáng kể (trong các trường hợp cạnh) để chuyển giải pháp của bạn sang số nguyên có dấu không? Tôi đã thử nghiệm bằng cách sử dụng fiddle của bạn làm cơ sở. set @val = '1.'; SELECT @val, LENGTH(CAST(@val AS SIGNED)) = IF(CAST(@val AS SIGNED) = 0, CAST(@val AS SIGNED), LENGTH(@val)) AS is_int;Việc tái cấu trúc này xử lý tất cả các trường hợp trên, nhưng ngay cả điều chỉnh của tôi cũng không xử lý -1.0 hoặc '-1.' Một lần nữa, một giải pháp siêu hay.
spen.smith

3

Thế còn:

WHERE table.field = "0" or CAST(table.field as SIGNED) != 0

để kiểm tra số và corrolary:

WHERE table.field != "0" and CAST(table.field as SIGNED) = 0

1
CAST (table.field)! = 0 sẽ không hoạt động vì nó cần một kiểu để truyền.
Riad

Điều này hoạt động hoàn hảo nếu bạn cần kiểm tra các mục không phải là số, điều này xứng đáng được +1. Các câu trả lời khác khó hơn để đảo ngược bài kiểm tra để tìm các mục không phải là số.
DrCord

Điều này không hoạt động đối với các số như "0000", "0" (khoảng trắng) và "7x" (được coi là một số).
Michael Grazebrook

@MichaelGrazebrook Tôi cho rằng bạn có thể thực hiện regexp cho hai trường hợp đầu tiên. "7x" được coi là một số? "0x7" là một số, nhưng 7x?
Tom Auger

1
@Tom Auger: Một câu trả lời khác đề cập đến các giải pháp loại regex. Những gì tôi có nghĩa là bởi "7x được coi là một con số" là tuyên bố này là đúng: chọn 7 = '7Q'
Michael Grazebrook

1

Tôi đã thử sử dụng các biểu thức chính quy được liệt kê ở trên, nhưng chúng không hoạt động cho những điều sau:

SELECT '12 INCHES' REGEXP '^(-|\\+){0,1}([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+|[0-9]+)$' FROM ...

Ở trên sẽ trả về 1( TRUE), nghĩa là kiểm tra chuỗi '12 INCHES 'so với biểu thức chính quy ở trên, trả về TRUE. Nó trông giống như một số dựa trên biểu thức chính quy được sử dụng ở trên. Trong trường hợp này, bởi vì số 12 ở đầu chuỗi, biểu thức chính quy hiểu nó như một số.

Phần sau sẽ trả về giá trị bên phải (tức là 0) vì chuỗi bắt đầu bằng ký tự thay vì chữ số

SELECT 'TOP 10' REGEXP '^(-|\\+){0,1}([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+|[0-9]+)$' FROM ...

Ở trên sẽ trả về 0( FALSE) vì phần đầu của chuỗi là văn bản chứ không phải số.

Tuy nhiên, nếu bạn đang xử lý các chuỗi có sự kết hợp của số và chữ cái bắt đầu bằng một số, bạn sẽ không nhận được kết quả như mong muốn. REGEXP sẽ diễn giải chuỗi là một số hợp lệ trong khi thực tế không phải vậy.


2
Điều này là không đúng. Bạn đã kiểm tra nó? Khi tôi chạy ví dụ đầu tiên của bạn, nó trả về FALSE, như mong đợi, bởi vì regex kết thúc bằng $nghĩa là cuối chuỗi, vì vậy nó chỉ kiểm tra các số, như dự định của tác giả.
spikyjt

1

Điều này hoạt động tốt cho VARCHAR khi nó bắt đầu bằng một số hoặc không ..

WHERE concat('',fieldname * 1) != fieldname 

có thể có những hạn chế khi bạn đến số NNNNE + - lớn hơn


Điều này dường như không hoạt động đối với các chuỗi ký tự đơnset @val = '5'; SELECT @val, concat('', @val * 1) != @val is_int;
spen.smith

0

đối với tôi điều duy nhất hoạt động là:

CREATE FUNCTION IsNumeric (SIN VARCHAR(1024)) RETURNS TINYINT
RETURN SIN REGEXP '^(-|\\+){0,1}([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+|[0-9]+)$';

từ kevinclark tất cả những thứ vô dụng khác trả lại cho tôi trong trường hợp 234jk456hoặc12 inches

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.