Come posso verificare se un valore è un numero intero in MySQL?


123

Vedo che all'interno di MySQL ci sono Cast()e Convert()funzioni per creare numeri interi da valori, ma c'è un modo per verificare se un valore è un numero intero? Qualcosa di simile is_int()in PHP è quello che sto cercando.


2
quindi purtroppo dobbiamo creare la funzione is_int () in Mysql
Yuda Prawira

Risposte:


214

Suppongo che tu voglia controllare un valore di stringa. Un modo carino è l'operatore REGEXP, che fa corrispondere la stringa a un'espressione regolare. Fallo semplicemente

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

questo è ragionevolmente veloce. Se il tuo campo è numerico, prova solo per

ceil(field) = field

anziché.


4
Il test 'ceil (field) = field' è una bella idea, ma come ha sottolineato @Jumpy, fallisce su dati non numerici: SELECT ceil ('four') = 'four'; -> 1
Matthew Cornell

3
@ MatthewCornell, ha detto se il tuo campo è numerico. In questo modo puoi verificare se un numero è un numero intero. Non funzionerà con le stringhe, ecco perché c'è la prima opzione.
Malfist

Se i dati potessero includere spazi vuoti, l'operazione fallirebbe. Considera l'idea di testare trim (campo), possibilmente con un arg in più per rimuovere le nuove righe.
Michael Grazebrook

il dato è numerico, può fare anche questo: select ((field% 1) = 0);
ThiamTeck

Grazie, ma per il confronto numerico, penso che non sia necessario (strcmp (ceil (field), field))
Alan Dixon

14

Confrontalo con un'espressione regolare.

cf http://forums.mysql.com/read.php?60,1907,38488#msg-38488 come citato di seguito:

Ri: clausola IsNumeric () in MySQL ??
Inserito da: kevinclark ()
Data: 8 agosto 2005 13:01


Sono d'accordo. Ecco una funzione che ho creato per 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]+)$';


Ciò consente un segno più / meno opzionale all'inizio, un punto decimale opzionale e le restanti cifre numeriche.


Grazie, la tua soluzione si occupa anche dei decimali
Ananda

12

Supponiamo di avere una colonna con un campo alfanumerico con voci come

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

e vuoi il valore numerico più alto da questa colonna db (in questo caso è 9582), questa query ti aiuterà

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

1
"10000" è un valore superiore, ma la tua query restituirà comunque "9582" .
Paul Spiegel

8

Ecco la soluzione semplice per esso supponendo che il tipo di dati sia varchar

select * from calender where year > 0

Restituirà vero se l'anno è numerico altrimenti falso


29
In un varchar, questo restituirà anche true se il primo carattere è numerico.
TuK

Non l'ho notato. voto
positivo il

8

Funziona anche:

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

per esempio

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

11
che dire SELECT CAST('12a34' AS UNSIGNED), che ritorna 12?
Mike C

1
Funziona perfettamente se devi testare elementi non numerici, questo merita più +1. Le altre risposte sono più difficili per invertire il test per trovare gli elementi non numerici.
DrCord

1
@DrCord questo non funziona per il caso descritto da Mike C, quindi è molto inaffidabile
jontro

4

Per verificare se un valore è Int in Mysql, possiamo utilizzare la seguente query. Questa query fornirà le righe con valori Int

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

Questo selezionerà anche numeri non interi (es. "3.5" ).
Paul Spiegel

4

Il meglio che potrei pensare a una variabile è un int È una combinazione con le funzioni di MySQL CAST()e LENGTH().
Questo metodo funzionerà su stringhe, interi, doppi / float tipi di dati.

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

guarda la demo http://sqlfiddle.com/#!9/ff40cd/44

fallirà se la colonna ha un singolo valore di carattere. se la colonna ha un valore "A", Cast ("A" come UNSIGNED) restituirà 0 e LENGTH (0) sarà 1. quindi LENGTH (Cast ('A' as UNSIGNED)) = LENGTH (0) restituirà 1 = 1 => 1

Il vero Waqas Malik è totalmente incapace di testare quel caso. la patch è.

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;

risultati

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

guarda la demo


fallirà se la colonna ha un singolo valore di carattere. se la colonna ha un valore "A", Cast ("A" come UNSIGNED) restituirà 0 e LENGTH (0) sarà 1. quindi LENGTH (Cast ('A' as UNSIGNED)) = LENGTH (0) restituirà 1 = 1 => 1
Waqas Malik

Grazie per il commento che il caso è stato davvero non testato @WaqasMalik sta lavorando e testando una patch in questo momento .. qualcosa del tipoSELECT "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

Questa è una soluzione così interessante. Penso che fallisca per interi negativi, cambia qualcosa di sostanziale (nei casi limite) per cambiare la tua soluzione in interi con segno? Ho provato a usare il tuo violino come base. 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;Questo refactoring gestisce tutti i casi precedenti, ma anche la mia regolazione non gestisce -1.0 o "-1". Ancora una volta, una soluzione fantastica.
spen.smith

3

Che dire:

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

per testare numerico e corrolare:

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

1
CAST (table.field)! = 0 non funzionerà in quanto necessita di un tipo per eseguire il cast.
Riad

Funziona perfettamente se devi testare elementi non numerici, questo merita più +1. Le altre risposte sono più difficili per invertire il test per trovare gli elementi non numerici.
DrCord

Questo non funziona per numeri come "0000", "0" (spazio) e "7x" (che è considerato un numero).
Michael Grazebrook

@MichaelGrazebrook Suppongo che potresti fare una regexp per i primi due casi. "7x" è considerato un numero? "0x7" è un numero, ma 7x?
Tom Auger

1
@ Tom Auger: Un'altra risposta ha riguardato le soluzioni di tipo regex. Quello che intendevo con "7x è considerato un numero" è che questa affermazione è vera: seleziona 7 = '7q'
Michael Grazebrook

1

Ho provato a utilizzare le espressioni regolari elencate sopra, ma non funzionano per quanto segue:

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

Quanto sopra restituirà return 1( TRUE), che significa il test della stringa '12 INCHES 'contro l'espressione regolare sopra, restituisce TRUE. Sembra un numero basato sull'espressione regolare usata sopra. In questo caso, poiché il 12 è all'inizio della stringa, l'espressione regolare lo interpreta come un numero.

Quanto segue restituirà il valore corretto (cioè 0) perché la stringa inizia con caratteri invece che con cifre

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

Quanto sopra restituirà 0( FALSE) perché l'inizio della stringa è testo e non numerico.

Tuttavia, se hai a che fare con stringhe che hanno una combinazione di numeri e lettere che iniziano con un numero, non otterrai i risultati desiderati. REGEXP interpreterà la stringa come un numero valido quando in realtà non lo è.


2
Questo non è corretto. L'hai testato? Quando eseguo il tuo primo esempio, restituisce FALSE, come previsto, perché la regex termina con $che significa la fine della stringa, quindi sta controllando solo i numeri, come previsto dall'autore.
spikyjt

1

Funziona bene per VARCHAR dove inizia con un numero o no ..

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

potrebbero avere limitazioni quando si arriva ai numeri NNNNE + - più grandi


Questo non sembra funzionare per stringhe di caratteri singoliset @val = '5'; SELECT @val, concat('', @val * 1) != @val is_int;
spen.smith il

0

per me l'unica cosa che funziona è:

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

da kevinclark tutti gli altri restituiscono cose inutili per me in caso di 234jk456o12 inches

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.