ตรวจสอบว่าค่าเป็นตัวเลขใน MySQL


159

มีวิธีการตรวจสอบว่าค่าเป็นจำนวนในแบบสอบถาม MySQL หรือไม่ เช่น

SELECT * 
FROM myTable 
WHERE isANumber(col1) = true

ฉันได้ทดสอบกลยุทธ์ 1 * col = col แต่อย่างใดมันล้มเหลวเมื่อมีการเรียกแบบสอบถามผ่านทาง PHP (คืนค่าจริงเมื่อไม่ควร) อย่างไรก็ตามใน phpMyAdmin แฮ็คก็ใช้งานได้ ซึ่งหมายความว่าการทดสอบของฉันทำงานตามที่คาดไว้ซื้อแอปพลิเคชันของฉันไม่ได้
Jahaziel

คำตอบ:


251

ซึ่งควรใช้งานได้ในกรณีส่วนใหญ่

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

มันไม่ทำงานสำหรับตัวเลขที่ไม่ได้มาตรฐานเช่น

  • 1e4
  • 1.2e5
  • 123. (ต่อท้ายทศนิยม)

ขอบคุณ. น่าเสียดายที่ฉันต้องการให้มันรับรู้ว่า 123 เป็นตัวเลข แต่ 123X ไม่ใช่
Urbycoz

1
@ Richard- ฉันเพิ่งอ่านข้อยกเว้นที่คุณให้ คิดว่าคุณหมายถึงอักขระ "e" ฉันเห็นสิ่งที่คุณหมายถึงตอนนี้
Urbycoz

เลขศูนย์นำหน้าไม่ใช่ปัญหาสำหรับนักพัฒนา sql ที่ชำนาญ --- การตัดแต่ง (นำ 0 จาก col1)
pimbrouwers

ฉันรู้ว่ามันเป็นโพสต์เก่า แต่ฉันใช้วิธีนี้ในการค้นหาของฉัน แต่ฉันมีปัญหามันตรวจพบ "2-Power" ว่า "2" ทำให้เกิดปัญหาเนื่องจากไม่ควรทำเช่นนั้น ความคิดใด ๆ
GRosay

1
สำหรับการต่อท้ายและเลขศูนย์นำหน้า (เช่น 023.12000): concat ('', col1 * 1) = '0' หรือ concat ('', col1 * 1) = IF (LOCATE ('.', col1), TRIM (BOTH ' 0 'จาก col1), TRIM (ส่วนที่เหลือ' 0 'จาก col1));
François Breton

299

คุณสามารถใช้ Regular Expression ได้เช่นกัน ...

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

การอ้างอิง: http://dev.mysql.com/doc/refman/5.1/en/regexp.html


70
เลือก * จาก myTable WHERE col1 REGEXP '^ [0-9] + $';
Dmitriy Kozmenko

7
คำตอบที่ยอมรับนั้นฉลาดจริงๆ แต่คำตอบนี้ตรงกว่าและฉันคิดว่ามันควรจะเป็นทางออกที่ยอมรับได้
pedromanoel

21
สำหรับกรณีของ "ไม่ตรงกัน": WHERE col1 NOT REGEXP...และสำหรับกรณีที่คุณอาจมีจุดทศนิยมให้ใช้ regex:^[0-9\.]+$
Robbie Averill

2
นอกจากนี้จะไม่ทำงานสำหรับสัญกรณ์วิทยาศาสตร์ใช้งานได้กับ ints เท่านั้น
David Wilkins

1
Regex migth จะยากที่จะอ่านสำหรับคนที่ไม่เคยใช้ แต่คุณสามารถทำสิ่งที่ดีจริงๆและระยะสั้นกับมัน
Olli

56

หากข้อมูลของคุณคือ 'ทดสอบ', 'test0', 'test1111', '111test', '111'

ในการเลือกระเบียนทั้งหมดที่มีข้อมูลอยู่ใน int:

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

ผลลัพธ์: '111'

(ใน regex, ^ หมายถึงเริ่มต้นและ $ หมายถึงสิ้นสุด)

ในการเลือกระเบียนทั้งหมดที่มีจำนวนเต็มหรือเลขทศนิยมอยู่:

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

ผลลัพธ์: '111' (เหมือนกับตัวอย่างล่าสุด)

ในที่สุดเมื่อต้องการเลือกระเบียนทั้งหมดที่มีหมายเลขให้ใช้สิ่งนี้:

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

ผลลัพธ์: 'test0' และ 'test1111' และ '111test' และ '111'


ฉันชอบวิธีนี้ดีกว่าเพราะชัดเจนและ "แฮ็ก" น้อยกว่าเคล็ดลับการต่อข้อมูล ขอบคุณ!
brokethebuildagain

8
ไม่ทำงานสำหรับค่าลบ ฉันจะแก้ไข regexp ที่เสนอดังนี้:REGEXP '^[+\-]?[0-9]+\\.?[0-9]*$'
Nicolas

ฉันว่าสัญลักษณ์ "+" ไม่จำเป็นคุณสามารถใช้แค่ "-?" แต่ถ้าคุณต้องการใช้คุณควรหนีมัน (และสัญลักษณ์ "-" ไม่จำเป็นต้องหลบหนี) .
ต. มุม

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

จะจับคู่ทศนิยมที่ลงนามแล้ว (เช่น-1.2, +0.2, 6, 2e9, 1.2e-10 )

ทดสอบ:

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;

ผลลัพธ์:

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

การสาธิต


3
ที่สมบูรณ์แบบ! ตอบเท่านั้นที่ครอบคลุมฐานจริงทั้งหมด ควรเป็นคำตอบที่ยอมรับได้
Dom

10

ส่งคืนแถวตัวเลข

ฉันพบวิธีแก้ปัญหาด้วยแบบสอบถามต่อไปนี้และทำงานได้สำหรับฉัน:

SELECT * FROM myTable WHERE col1 > 0;

แบบสอบถามนี้ส่งคืนแถวที่มีคอลัมน์จำนวนมากกว่าศูนย์เท่านั้น col1

ส่งคืนแถวที่ไม่ใช่ตัวเลข

หากคุณต้องการตรวจสอบคอลัมน์ไม่ใช่ตัวเลขลองอันนี้ด้วยเคล็ดลับ ( !col1 > 0):

SELECT * FROM myTable WHERE !col1 > 0;

สิ่งนี้ใช้ไม่ได้หากคุณมีสตริงที่ขึ้นต้นด้วยตัวเลข "123abc" มันจะถูกส่งกลับในคำสั่งแถวตัวเลขของคุณและไม่อยู่ในคำสั่งที่ไม่ใช่ตัวเลข
JStephen

@JStephen คุณถูกต้อง! เพราะSELECT * FROM myTable WHERE col1 = 123;ข้อความค้นหาจะส่งคืนแถวแม้ค่า col คือ123abc
Bora

9

คำตอบนี้คล้ายกับ Dmitry แต่จะอนุญาตให้ใช้ทศนิยมเช่นเดียวกับตัวเลขบวกและลบ

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

8

ใช้ UDF (ฟังก์ชั่นที่ผู้ใช้กำหนด)

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

จากนั้นเมื่อคุณสอบถาม

select isnumber('383XXXX') 

- ผลตอบแทน 0

select isnumber('38333434') 

- ผลตอบแทน 1

เลือกหมายเลข (mycol) mycol1, col2, colx จาก tablex; - จะส่งคืน 1s และ 0s สำหรับคอลัมน์ mycol1

- คุณสามารถเพิ่มฟังก์ชั่นเพื่อใช้เป็นทศนิยมสัญลักษณ์ทางวิทยาศาสตร์ ฯลฯ ...

ข้อดีของการใช้ UDF คือคุณสามารถใช้ทางด้านซ้ายหรือด้านขวาของการเปรียบเทียบ "where clause" ของคุณ สิ่งนี้ทำให้ SQL ของคุณง่ายขึ้นอย่างมากก่อนที่จะถูกส่งไปยังฐานข้อมูล:

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

หวังว่านี่จะช่วยได้


5

อีกทางเลือกหนึ่งที่ดูเหมือนว่าเร็วกว่า REGEXP บนคอมพิวเตอร์ของฉัน

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

นี่จะเลือกแถวทั้งหมดที่ col1 เริ่มต้นด้วยค่าตัวเลข


2
แล้วถ้าค่าเป็นศูนย์ล่ะ
Urbycoz

1
ฉันเดาว่าคุณสามารถเพิ่มAND col1<>0เพื่อจัดการข้อยกเว้นนั้นได้
Urbycoz

มันเป็นความจริงที่มันใช้งานไม่ได้กับค่าศูนย์ แต่ใช้ได้ดีกับตัวเลขที่มีเบาะเช่น 004 คำตอบที่ยอมรับไม่ได้สำหรับตัวเลขที่มีเบาะ
Abbas

ฉันคิดว่านี่เป็นวิธีที่ดีที่สุดในการตรวจสอบหมายเลข เป็นเพียงว่าเราจำเป็นต้องเพิ่มคำสั่งหรือสำหรับการตรวจสอบศูนย์เป็น SELECT * จาก myTable WHERE col1 * 0! = col1 OR col1 = '0';
Binu Raman

'1a'ฉันได้รับในเชิงบวกเท็จ BTW: เทียบเท่ากับWHERE col1 <> 0- rextester.com/DJIS1493
Paul Spiegel

4

ยังขาดรุ่นง่าย ๆ นี้:

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

(ควรเพิ่มเร็วกว่าการคูณ)

หรือเวอร์ชั่นที่ช้าที่สุดสำหรับการเล่นเพิ่มเติม:

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

3
ถ้าฉันไม่เข้าใจผิด MySQL จะแปลงสตริงใด ๆ ให้เป็น 0 ดังนั้นสิ่งนี้จะไม่แยกความแตกต่างระหว่างสตริงและตัวเลขทั้งสองจะกลับมาเหมือนเดิม
Ivan McA

3
'a' + 0 = 'a'คือ TRUE
Paul Spiegel

3

ฉันแนะนำ: หากการค้นหาของคุณง่ายคุณสามารถใช้ `

column*1 = column

`โอเปอเรเตอร์ที่น่าสนใจ :) ทำงานและเร็วกว่าในฟิลด์ varchar / char

SELECT * จาก myTable WHERE คอลัมน์ * 1 = คอลัมน์;

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

1
คุณรู้หรือไม่ว่าใน MySQL ทั้งสองselect 'aaa123' >= 0และ select '123aaa' >= 0คืนจริงหรือไม่
Grzegorz Smulko

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

เครื่องหมาย ofcourse (0) เป็นศูนย์ แต่จากนั้นคุณสามารถ จำกัด การสืบค้น ...

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

อัปเดต: สิ่งนี้ไม่น่าเชื่อถือ 100% เนื่องจาก "1abc" จะส่งคืนสัญญาณของ 1 แต่ "ab1c" จะกลับเป็นศูนย์ ... ดังนั้นสิ่งนี้จะใช้ได้กับข้อความที่ไม่ได้ขึ้นต้นด้วยตัวเลขเท่านั้น




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