Mendeteksi jika nilainya angka di MySQL


159

Apakah ada cara untuk mendeteksi apakah suatu nilai adalah angka dalam permintaan MySQL? Seperti

SELECT * 
FROM myTable 
WHERE isANumber(col1) = true

Saya telah menguji strategi 1 * col = col, tetapi entah bagaimana gagal ketika kueri dipanggil melalui PHP (mengembalikan true ketika seharusnya tidak). Namun di phpMyAdmin, peretasan bekerja. Ini berarti pengujian saya berperilaku seperti yang diharapkan, beli aplikasi saya tidak.
Jahaziel

Jawaban:


251

Ini seharusnya bekerja dalam banyak kasus.

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

Itu tidak berfungsi untuk nomor non-standar seperti

  • 1e4
  • 1.2e5
  • 123. (membuntuti desimal)

Terima kasih. Sayangnya saya membutuhkannya untuk mengenali bahwa 123 adalah angka, tetapi 123X tidak.
Urbycoz

1
@ Richard- Saya baru saja membaca pengecualian yang Anda berikan. Kupikir kamu berarti karakter "e". Saya mengerti maksud Anda sekarang.
Urbycoz

Angka nol utama tidak menjadi masalah bagi pengembang sql yang cekatan --- trim (memimpin 0 dari col1)
pimbrouwers

Saya tahu ini adalah posting lama tapi saya menggunakan metode ini dalam permintaan saya. Tapi saya punya masalah, mendeteksi "2-Power" sebagai "2" menyebabkan masalah karena tidak seharusnya melakukan itu. Ada ide ?
GRosay

1
Untuk nol di belakang dan di depan (mis. 023.12000): concat ('', col1 * 1) = '0' ATAU concat ('', col1 * 1) = IF (LOCATE ('.', Col1), TRIM (KEDUA ' 0 'FROM col1), TRIM (LEADING' 0 'FROM col1));
François Breton

299

Anda dapat menggunakan Ekspresi Reguler juga ... itu akan seperti:

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

Referensi: http://dev.mysql.com/doc/refman/5.1/en/regexp.html


70
PILIH * DARI myTable WHERE col1 REGEXP '^ [0-9] + $';
Dmitriy Kozmenko

7
Jawaban yang diterima benar-benar pintar, tetapi jawaban ini lebih langsung, dan saya pikir itu harus menjadi solusi yang diterima.
pedromanoel

21
Untuk kasus "tidak cocok":, WHERE col1 NOT REGEXP...dan untuk kasus di mana Anda mungkin memiliki titik desimal, gunakan regex:^[0-9\.]+$
Robbie Averill

2
Juga tidak akan berfungsi untuk notasi ilmiah, hanya bekerja untuk int
David Wilkins

1
Regex migth sulit dibaca bagi orang yang tidak pernah menggunakannya, tetapi Anda dapat melakukan hal-hal yang sangat hebat dan singkat dengannya
Olli

56

Jika data Anda adalah 'test', 'test0', 'test1111', '111test', '111'

Untuk memilih semua catatan di mana data int sederhana:

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

Hasil: '111'

(Dalam regex, ^ berarti mulai, dan $ berarti akhir)

Untuk memilih semua catatan di mana bilangan bulat atau angka desimal ada:

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

Hasil: '111' (sama seperti contoh terakhir)

Akhirnya, untuk memilih semua catatan di mana nomor ada, gunakan ini:

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

Hasil: 'test0' dan 'test1111' dan '111test' dan '111'


Saya suka pendekatan ini lebih baik karena lebih jelas dan kurang "retas" daripada trik penyatuan. Terima kasih!
brokethebuildagain

8
Tidak bekerja untuk nilai negatif. Saya akan mengubah regexp yang diusulkan sebagai berikut:REGEXP '^[+\-]?[0-9]+\\.?[0-9]*$'
Nicolas

Saya akan mengatakan simbol "+" tidak perlu, Anda bisa menggunakan hanya "-?", Tetapi jika Anda ingin menggunakannya, Anda harus menghindarinya (dan simbol "-" tidak perlu diloloskan) .
T. Corner

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

Juga akan cocok dengan desimal yang ditandatangani (seperti -1.2, +0.2, 6., 2e9, 1.2e-10 ).

Uji:

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;

Hasil:

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

Demo


3
Sempurna! Hanya jawaban yang benar-benar mencakup semua pangkalan. Seharusnya jawaban yang diterima.
Dom

10

Mengembalikan baris numerik

Saya menemukan solusinya dengan permintaan berikut dan berfungsi untuk saya:

SELECT * FROM myTable WHERE col1 > 0;

Baris pengembalian permintaan ini hanya memiliki kolom angka di atas nol col1

Mengembalikan baris non numerik

jika Anda ingin memeriksa kolom bukan angka coba ini dengan trik ( !col1 > 0):

SELECT * FROM myTable WHERE !col1 > 0;

Ini tidak berfungsi, jika Anda memiliki string yang dimulai dengan angka "123abc" itu akan dikembalikan dalam pernyataan baris numerik Anda dan bukan dalam pernyataan non-numerik.
JStephen

@JStephen Kamu benar! Karena SELECT * FROM myTable WHERE col1 = 123;permintaan akan mengembalikan baris, bahkan nilai col123abc
Bora

9

Jawaban ini mirip dengan Dmitry, tetapi akan memungkinkan untuk desimal serta angka positif dan negatif.

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

8

menggunakan UDF (fungsi yang ditentukan pengguna).

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

Lalu ketika Anda bertanya

select isnumber('383XXXX') 

- mengembalikan 0

select isnumber('38333434') 

- mengembalikan 1

pilih isnumber (mycol) mycol1, col2, colx dari tablex; - akan mengembalikan 1s dan 0s untuk kolom mycol1

--Anda dapat meningkatkan fungsi untuk mengambil desimal, notasi ilmiah, dll ...

Keuntungan menggunakan UDF adalah Anda dapat menggunakannya di sisi kiri atau kanan perbandingan "where clause" Anda. ini sangat menyederhanakan SQL Anda sebelum dikirim ke database:

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

semoga ini membantu.


5

Alternatif lain yang tampaknya lebih cepat daripada REGEXP di komputer saya adalah

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

Ini akan memilih semua baris tempat col1 dimulai dengan nilai numerik.


2
Bagaimana jika nilainya nol?
Urbycoz

1
Saya kira Anda bisa menambahkan AND col1<>0untuk menangani pengecualian itu.
Urbycoz

Memang benar bahwa itu tidak bekerja untuk nilai nol tetapi itu bekerja dengan baik untuk angka empuk, misalnya 004. Jawaban yang diterima tidak bekerja untuk angka empuk
Abbas

Saya pikir ini adalah cara terbaik untuk memeriksa angka. Hanya saja kita perlu menambahkan pernyataan ATAU untuk memeriksa nol, karena SELECT * DARI myTable WHERE col1 * 0! = Col1 ATAU col1 = '0';
Binu Raman

Saya mendapatkan false positive '1a'. BTW: ini setara dengan WHERE col1 <> 0- rextester.com/DJIS1493
Paul Spiegel

4

Masih melewatkan versi sederhana ini:

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

(penambahan harus lebih cepat dari perkalian)

Atau versi paling lambat untuk bermain lebih lanjut:

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

3
Kecuali saya salah paham, MySQL mengonversi string apa pun menjadi 0 sehingga ini tidak akan membedakan antara string dan angka, keduanya akan mengembalikan yang sama.
Ivan McA

3
'a' + 0 = 'a'BENAR
Paul Spiegel

3

Saya sarankan: jika pencarian Anda sederhana, Anda dapat menggunakan `

column*1 = column

`operator yang menarik :) bekerja dan lebih cepat daripada di bidang varchar / char

PILIH * DARI myTable WHERE kolom * 1 = kolom;

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

1
Apakah Anda sadar bahwa di MySQL keduanya select 'aaa123' >= 0dan select '123aaa' >= 0kembali benar?
Grzegorz Smulko

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

tanda ofcourse (0) adalah nol, tetapi kemudian Anda dapat membatasi kueri untuk ...

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

UPDATE: Ini tidak 100% dapat diandalkan, karena "1abc" akan mengembalikan tanda 1, tetapi "ab1c" akan mengembalikan nol ... jadi ini hanya bisa berfungsi untuk teks yang tidak dimulai dengan angka.


0

Anda bisa menggunakan CAST

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


-1

Coba Dividing / 1

select if(value/1>0 or value=0,'its a number', 'its not a number') from table
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.