MySQL'de bir değerin tam sayı olup olmadığını nasıl kontrol ederim?


123

MySQL içinde değerlerden tamsayılar oluşturmak için Cast()ve Convert()işlevler olduğunu görüyorum, ancak bir değerin tam sayı olup olmadığını kontrol etmenin herhangi bir yolu var mı? is_int()PHP'deki gibi bir şey aradığım şey .


2
ne yazık ki Mysql'de is_int () fonksiyonu oluşturmalıyız
Yuda Prawira

Yanıtlar:


215

Bir dize değerini kontrol etmek istediğinizi varsayacağım. Güzel bir yol, dizeyi normal bir ifadeyle eşleştiren REGEXP operatörüdür. Basitçe yap

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

bu oldukça hızlı. Alanınız sayısal ise, sadece test edin

ceil(field) = field

yerine.


4
'Ceil (alan) = alan' testi güzel bir fikir, ancak @Jumpy'nin belirttiği gibi sayısal olmayan verilerde başarısız oluyor: SELECT ceil ('dört') = 'dört'; -> 1
Matthew Cornell

3
@MatthewCornell, Alanınız sayısal ise dedi. Böylece, bir sayının tam sayı olup olmadığını test edebilirsiniz. Dizeler üzerinde çalışmaz, bu yüzden ilk seçenek oradadır.
Malfist

Veriler beyaz boşluk içeriyorsa, bu başarısız olur. Döşeme (alan) 'ı, muhtemelen yeni satırları kaldırmak için fazladan bir argümanla test etmeyi düşünün.
Michael Grazebrook

veriler sayısaldır, bunu da yapabilir: select ((alan% 1) = 0);
ThiamTeck

Teşekkürler, ama sayısal karşılaştırma için ihtiyacın olmadığını düşünüyorum (strcmp (ceil (alan), alan))
Alan Dixon

14

Normal bir ifadeyle eşleştirin.

cf http://forums.mysql.com/read.php?60,1907,38488#msg-38488 aşağıda alıntılandığı gibi:

Re: MySQL'de IsNumeric () yan tümcesi?
Gönderen: kevinclark ()
Tarih: 08 Ağustos 2005 13:01


Katılıyorum. İşte MySQL 5 için oluşturduğum bir işlev:

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


Bu, başlangıçta isteğe bağlı bir artı / eksi işareti, isteğe bağlı bir ondalık nokta ve geri kalan sayısal basamaklar sağlar.


Teşekkürler, çözümünüz ondalık sayılarla da ilgileniyor
Ananda

12

Aşağıdaki gibi girişlere sahip alfanümerik alana sahip bir sütunumuz olduğunu varsayalım

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

ve bu db sütunundan en yüksek sayısal değeri istiyorsanız (bu durumda 9582'dir), bu durumda bu sorgu size yardımcı olacaktır

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

1
"10000" daha yüksek, ancak sorgunuz yine de "9582" döndürür .
Paul Spiegel

8

Veri türünün varchar olduğunu varsayarak bunun için basit bir çözüm

select * from calender where year > 0

Yıl sayısal, aksi takdirde yanlışsa doğru dönecektir


29
Bir varchar'da, ilk karakter sayısal ise bu da true döndürür.
TuK

Bunu fark etmedim. yorumunuzu
oylayarak

8

Bu aynı zamanda çalışır:

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

Örneğin

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

11
Ne hakkında SELECT CAST('12a34' AS UNSIGNED), hangi döner 12?
Mike C

1
Sayısal olmayan öğeleri test etmeniz gerektiğinde bu mükemmel çalışır, bu daha fazla + 1'i hak eder. Diğer cevaplar, sayısal olmayan maddeleri bulmak için testi tersine çevirmek daha zordur.
DrCord

1
@DrCord bu, Mike C'nin tarif ettiği dava için işe yaramıyor, bu nedenle çok güvenilmez
jontro

4

Mysql'de bir değerin Int olup olmadığını kontrol etmek için aşağıdaki sorguyu kullanabiliriz. Bu sorgu, Int değerleri olan satırları verecektir.

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

Bu aynı zamanda tamsayı olmayan sayıları da seçecektir (ör. '3.5' ).
Paul Spiegel

4

Bir değişken hakkında düşünebildiğim en iyi şey, bir int MySQL'in fonksiyonları CAST()ve LENGTH().
Bu yöntem dizeler, tam sayılar, çiftler / kayan veri türleri üzerinde çalışacaktır.

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

demoya bakın http://sqlfiddle.com/#!9/ff40cd/44

sütun tek bir karakter değerine sahipse başarısız olur. sütun 'A' değerine sahipse, Yayınlama (İmzalanmamış olarak 'A') 0 olarak değerlendirilir ve UZUNLUK (0) 1 olur, bu nedenle UZUNLUK (Oyuncular ('A' İMZALANMAMIŞ olarak 'A') = UZUNLUK (0) olarak değerlendirilir 1 = 1 => 1

True Waqas Malik, bu davayı test etmek için tamamen sisli. yama.

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;

Sonuçlar

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

bkz demo


sütun tek bir karakter değerine sahipse başarısız olur. sütun 'A' değerine sahipse, Yayınlama (İmzalanmamış olarak 'A') 0 olarak değerlendirilir ve UZUNLUK (0) 1 olur, bu nedenle UZUNLUK (Oyuncular ('A' İMZALANMAMIŞ olarak 'A') = UZUNLUK (0) olarak değerlendirilir 1 = 1 => 1
Waqas Malik

Yorum için teşekkürler vaka çalışma ve şu anda bir yama testi gerçekten @WaqasMalik denenmemiş olduğunu .. gibi bir şeySELECT "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

Bu çok güzel bir çözüm. Negatif tamsayılar için başarısız olduğunu düşünüyorum, çözümünüzü işaretli tamsayılara geçirmek önemli (uç durumlarda) herhangi bir şeyi değiştiriyor mu? Kemanınızı temel olarak kullanarak test ediyorum. 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;Bu yeniden düzenleme yukarıdaki tüm durumları ele alır, ancak benim ayarlamam bile -1.0 veya '-1'i işlemiyor. Yine süper harika bir çözüm.
spen.smith

3

Ne dersin:

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

sayısal ve sonucu test etmek için:

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

1
CAST (table.field)! = 0, bir türe ihtiyaç duyduğu için çalışmayacaktır.
Riad

Sayısal olmayan öğeleri test etmeniz gerektiğinde bu mükemmel çalışır, bu daha fazla + 1'i hak eder. Diğer cevaplar, sayısal olmayan maddeleri bulmak için testi tersine çevirmek daha zordur.
DrCord

Bu, "0000", "0" (boşluk) ve "7x" (sayı olarak kabul edilir) gibi sayılar için çalışmaz.
Michael Grazebrook

@MichaelGrazebrook Sanırım ilk iki durum için bir regexp yapabilirsiniz. "7x" bir sayı olarak kabul edilir? "0x7" bir sayıdır, ancak 7x?
Tom Auger

1
@Tom Auger: Başka bir cevap, normal ifade tipi çözümleri kapsıyordu. "7x bir sayı olarak kabul edilir" ile kastettiğim, bu ifadenin doğru olduğu: 7 = '7q' seçin
Michael Grazebrook

1

Yukarıda listelenen normal ifadeleri kullanmayı denedim, ancak aşağıdakiler için çalışmıyorlar:

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

Yukarıdakiler 1( TRUE) döndürür , yani '12 İNÇ 'dizesinin yukarıdaki normal ifadeye göre test edilmesi anlamına gelir TRUE. Yukarıda kullanılan normal ifadeye dayalı bir sayıya benziyor. Bu durumda, 12 dizenin başında olduğu için normal ifade onu bir sayı olarak yorumlar.

0Dize rakamlar yerine karakterlerle başladığından, aşağıdaki doğru değeri (yani ) döndürecektir

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

Yukarıdakiler 0( FALSE) döndürür çünkü dizenin başlangıcı sayısal değil metindir.

Bununla birlikte, bir sayı ile başlayan sayıların ve harflerin karışımından oluşan dizelerle uğraşıyorsanız, istediğiniz sonuçları alamazsınız. REGEXP, dizeyi gerçekte öyle olmasa da geçerli bir sayı olarak yorumlar.


2
Bu yanlış. Test ettin mi İlk örneğinizi çalıştırdığımda FALSE, beklendiği gibi geri dönüyor , çünkü normal ifade ile bitiyor, $bu da dizenin sonu anlamına geliyor, bu nedenle yazarın tasarladığı şekilde yalnızca sayıları kontrol ediyor.
spikyjt

1

Bu, bir sayı ile başlayıp başlamadığı VARCHAR için işe yarar.

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

daha büyük NNNNE + - sayılarına ulaştığınızda kısıtlamalar olabilir


Bu tek karakter dizeleri için işe yaramıyor gibi görünüyorset @val = '5'; SELECT @val, concat('', @val * 1) != @val is_int;
spen.smith

0

benim için işe yarayan tek şey şudur:

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

kevinclark'tan benim için diğer tüm işe yaramaz şeyleri iade et 234jk456veya12 inches

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.