ฉันจะตรวจสอบได้อย่างไรว่าค่าเป็นจำนวนเต็มใน MySQL หรือไม่


123

ฉันเห็นว่าภายใน MySQL มีCast()และConvert()ฟังก์ชันในการสร้างจำนวนเต็มจากค่าต่างๆ แต่มีวิธีใดในการตรวจสอบว่าค่าเป็นจำนวนเต็มหรือไม่? สิ่งที่ชอบis_int()ใน PHP คือสิ่งที่ฉันกำลังมองหา


2
น่าเศร้าที่เราต้องสร้าง is_int () function ใน Mysql
Yuda Prawira

คำตอบ:


215

ฉันจะถือว่าคุณต้องการตรวจสอบค่าสตริง วิธีหนึ่งที่ดีคือตัวดำเนินการ REGEXP จับคู่สตริงกับนิพจน์ทั่วไป เพียงแค่ทำ

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

เร็วพอสมควร หากฟิลด์ของคุณเป็นตัวเลขให้ทดสอบ

ceil(field) = field

แทน.


4
การทดสอบ 'ceil (field) = field' เป็นความคิดที่ดี แต่ตามที่ @Jumpy ชี้ให้เห็นมันล้มเหลวในข้อมูลที่ไม่ใช่ตัวเลข: SELECT ceil ('four') = 'four'; -> 1
Matthew Cornell

3
@MatthewCornell เขาบอกว่าถ้าฟิลด์ของคุณเป็นตัวเลข เพื่อให้คุณสามารถทดสอบว่าตัวเลขเป็นจำนวนเต็มหรือไม่ มันใช้ไม่ได้กับสตริงนั่นคือเหตุผลที่ตัวเลือกแรกอยู่ที่นั่น
Malfist

หากข้อมูลอาจมีช่องว่างการดำเนินการนี้จะล้มเหลว ลองทดสอบการตัดแต่ง (ฟิลด์) โดยอาจมีอาร์กิวเมนต์พิเศษเพื่อลบบรรทัดใหม่
Michael Grazebrook

ข้อมูลเป็นตัวเลขอาจทำได้เช่นกัน: select ((field% 1) = 0);
ThiamTeck

ขอบคุณ แต่สำหรับการเปรียบเทียบตัวเลขฉันคิดว่าคุณไม่จำเป็นต้อง (strcmp (ceil (ฟิลด์), ฟิลด์))
Alan Dixon

14

จับคู่กับนิพจน์ทั่วไป

cf http://forums.mysql.com/read.php?60,1907,38488#msg-38488ดังที่ยกมาด้านล่าง:

เรื่อง IsNumeric () clause ใน MySQL ??
โพสต์โดย: kevinclark ()
วันที่: 08 สิงหาคม 2548 01:01 น


ฉันเห็นด้วย. นี่คือฟังก์ชั่นที่ฉันสร้างขึ้นสำหรับ 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]+)$';


ซึ่งอนุญาตให้มีเครื่องหมายบวก / ลบที่เป็นทางเลือกที่จุดเริ่มต้นจุดทศนิยมที่เป็นทางเลือกหนึ่งจุดและหลักตัวเลขที่เหลือ


ขอบคุณทางออกของคุณดูแลทศนิยมด้วย
อนันดา

12

สมมติว่าเรามีคอลัมน์ที่มีฟิลด์ตัวอักษรและตัวเลขที่มีรายการเช่น

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

และคุณต้องการค่าตัวเลขสูงสุดจากคอลัมน์ db นี้ (ในกรณีนี้คือ 9582) แบบสอบถามนี้จะช่วยคุณ

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

1
'10000'เป็นที่สูงขึ้น แต่ยังคงค้นหาของคุณจะกลับมา'9582'
Paul Spiegel

8

นี่คือวิธีง่ายๆสำหรับมันโดยสมมติว่าประเภทข้อมูลคือ varchar

select * from calender where year > 0

มันจะคืนค่าจริงถ้าปีเป็นตัวเลขอื่นเท็จ


29
ใน varchar สิ่งนี้จะคืนค่าจริงด้วยหากอักขระตัวแรกเป็นตัวเลข
TuK

ไม่ได้สังเกตว่า. โหวตความคิดเห็นของคุณ :)
Jayjitraj

8

สิ่งนี้ยังใช้งานได้:

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

ตัวอย่างเช่น

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

11
สิ่งที่เกี่ยวกับSELECT CAST('12a34' AS UNSIGNED)ซึ่งผลตอบแทน12?
Mike C

1
วิธีนี้ใช้งานได้ดีหากคุณต้องการทดสอบรายการที่ไม่ใช่ตัวเลขสิ่งนี้สมควรได้รับ +1 เพิ่มเติม คำตอบอื่น ๆ ยากที่จะย้อนกลับการทดสอบเพื่อค้นหารายการที่ไม่ใช่ตัวเลข
DrCord

1
@DrCord สิ่งนี้ใช้ไม่ได้กับกรณีที่ Mike C อธิบายไว้ดังนั้นจึงไม่น่าเชื่อถือมาก
jontro

4

ในการตรวจสอบว่าค่าเป็น Int ใน Mysql หรือไม่เราสามารถใช้แบบสอบถามต่อไปนี้ แบบสอบถามนี้จะให้แถวที่มีค่า Int

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

นอกจากนี้ยังจะเลือกตัวเลขที่ไม่ใช่จำนวนเต็ม (เช่น'3.5' )
Paul Spiegel

4

สิ่งที่ดีที่สุดที่ฉันสามารถนึกถึงตัวแปรคือ int เป็นการผสมผสานกับฟังก์ชันของ MySQL CAST()และLENGTH().
วิธีนี้จะใช้ได้กับสตริง, จำนวนเต็ม, คู่ / ลอยประเภทข้อมูล

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

ดูการสาธิตhttp://sqlfiddle.com/#!9/ff40cd/44

มันจะล้มเหลวหากคอลัมน์มีค่าอักขระเดียว ถ้าคอลัมน์มีค่า 'A' ดังนั้น Cast ('A' เป็น UNSIGNED) จะประเมินเป็น 0 และ LENGTH (0) จะเป็น 1 ดังนั้น LENGTH (Cast ('A' as UNSIGNED)) = LENGTH (0) จะประเมินเป็น 1 = 1 => 1

True Waqas Malik ถูกหมอกลงโดยสิ้นเชิงเพื่อทดสอบกรณีนั้น แพทช์คือ.

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;

ผล

**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      |

ดูการสาธิต


มันจะล้มเหลวหากคอลัมน์มีค่าอักขระเดียว ถ้าคอลัมน์มีค่า 'A' ดังนั้น Cast ('A' เป็น UNSIGNED) จะประเมินเป็น 0 และ LENGTH (0) จะเป็น 1 ดังนั้น LENGTH (Cast ('A' as UNSIGNED)) = LENGTH (0) จะประเมินเป็น 1 = 1 => 1
Waqas Malik

ขอบคุณสำหรับความคิดเห็นที่ว่ากรณีนี้ยังไม่ได้ทดสอบอย่างแท้จริง @WaqasMalik กำลังทำงานและทดสอบแพทช์ในขณะนี้ .. สิ่งที่ชอบ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

นี่เป็นวิธีแก้ปัญหาที่ยอดเยี่ยม ฉันคิดว่ามันล้มเหลวสำหรับจำนวนเต็มลบมันเปลี่ยนแปลงอะไรที่สำคัญ (ในกรณี edge) เพื่อเปลี่ยนโซลูชันของคุณเป็นจำนวนเต็มที่ลงนามหรือไม่? ฉันทดสอบโดยใช้ซอของคุณเป็นฐาน 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;การปรับโครงสร้างใหม่นี้จัดการกับกรณีข้างต้นทั้งหมด แต่แม้แต่การปรับของฉันก็ไม่รองรับ -1.0 หรือ '-1' อีกครั้งวิธีแก้ปัญหาที่ยอดเยี่ยม
spen.smith

3

สิ่งที่เกี่ยวกับ:

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

เพื่อทดสอบตัวเลขและโคโรลารี:

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

1
CAST (table.field)! = 0 จะไม่ทำงานเนื่องจากต้องใช้ประเภทในการแคสต์
Riad

วิธีนี้ใช้งานได้ดีหากคุณต้องการทดสอบรายการที่ไม่ใช่ตัวเลขสิ่งนี้สมควรได้รับ +1 เพิ่มเติม คำตอบอื่น ๆ ยากที่จะย้อนกลับการทดสอบเพื่อค้นหารายการที่ไม่ใช่ตัวเลข
DrCord

ใช้ไม่ได้กับตัวเลขเช่น "0000", "0" (ช่องว่าง) และ "7x" (ซึ่งถือเป็นตัวเลข)
Michael Grazebrook

@MichaelGrazebrook ฉันคิดว่าคุณสามารถทำ regexp สำหรับสองกรณีแรกได้ "7x" ถือเป็นตัวเลขหรือไม่? "0x7" เป็นตัวเลข แต่ 7x?
Tom Auger

1
@ Tom Auger: คำตอบอื่นที่ครอบคลุมถึงโซลูชันประเภท regex สิ่งที่ฉันหมายถึง "7x ถือเป็นตัวเลข" คือข้อความนี้เป็นจริง: select 7 = '7q'
Michael Grazebrook

1

ฉันได้ลองใช้นิพจน์ทั่วไปตามรายการข้างต้นแล้ว แต่ไม่สามารถใช้งานได้กับสิ่งต่อไปนี้:

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

ข้างต้นจะส่งกลับ1( TRUE) ซึ่งหมายถึงการทดสอบสตริง '12 นิ้ว 'เทียบกับนิพจน์ทั่วไปด้านบนจะส่งกลับTRUEกับการแสดงออกปกติข้างต้นผลตอบแทน ดูเหมือนตัวเลขตามนิพจน์ทั่วไปที่ใช้ข้างต้น ในกรณีนี้เนื่องจาก 12 อยู่ที่จุดเริ่มต้นของสตริงนิพจน์ทั่วไปจึงตีความเป็นตัวเลข

ต่อไปนี้จะส่งคืนค่าที่ถูกต้อง (เช่น0) เนื่องจากสตริงเริ่มต้นด้วยอักขระแทนตัวเลข

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

ข้างต้นจะส่งกลับ0( FALSE) เนื่องจากจุดเริ่มต้นของสตริงเป็นข้อความไม่ใช่ตัวเลข

อย่างไรก็ตามหากคุณกำลังจัดการกับสตริงที่มีตัวเลขและตัวอักษรผสมกันซึ่งขึ้นต้นด้วยตัวเลขคุณจะไม่ได้ผลลัพธ์ที่ต้องการ REGEXP จะตีความสตริงว่าเป็นตัวเลขที่ถูกต้องเมื่อในความเป็นจริงมันไม่ใช่


2
สิ่งนี้ไม่ถูกต้อง คุณทดสอบหรือไม่ เมื่อฉันเรียกใช้ตัวอย่างแรกของคุณมันจะส่งกลับFALSEตามที่คาดไว้เนื่องจาก regex ลงท้ายด้วย$ซึ่งหมายถึงจุดสิ้นสุดของสตริงดังนั้นจึงตรวจสอบเฉพาะตัวเลขตามที่ผู้เขียนตั้งใจไว้
spikyjt

1

สิ่งนี้ใช้ได้ดีกับ VARCHAR ที่ขึ้นต้นด้วยตัวเลขหรือไม่ ..

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

อาจมีข้อ จำกัด เมื่อคุณไปถึงหมายเลข NNNNE + - ที่ใหญ่กว่า


ดูเหมือนจะใช้ไม่ได้กับสตริงถ่านเดี่ยวset @val = '5'; SELECT @val, concat('', @val * 1) != @val is_int;
spen.smith

0

สำหรับฉันสิ่งเดียวที่ได้ผลคือ:

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

จาก kevinclark ส่งคืนสิ่งที่ไร้ประโยชน์สำหรับฉันในกรณีของ234jk456หรือ12 inches

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.