Comment vérifier si une valeur est un entier dans MySQL?

123

Je vois que dans MySQL il y a Cast()et des Convert()fonctions pour créer des entiers à partir de valeurs, mais y a-t-il un moyen de vérifier si une valeur est un entier? Quelque chose comme is_int()en PHP est ce que je recherche.

Craig Nakamoto
la source
2
malheureusement, nous devons créer la fonction is_int () dans Mysql
Yuda Prawira

Réponses:

214

Je suppose que vous voulez vérifier une valeur de chaîne. Une manière intéressante est l'opérateur REGEXP, qui fait correspondre la chaîne à une expression régulière. Faites simplement

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

c'est raisonnablement rapide. Si votre champ est numérique, testez simplement

ceil(field) = field

au lieu.

Nerveux
la source
4
Le test 'ceil (field) = field' est une bonne idée, mais comme @Jumpy l'a souligné, il échoue sur des données non numériques: SELECT ceil ('four') = 'four'; -> 1
Matthew Cornell
3
@MatthewCornell, Il a dit que si votre champ était numérique. C'est ainsi que vous pouvez tester si un nombre est un entier. Cela ne fonctionnera pas sur les chaînes, c'est pourquoi la première option est là.
Malfist
Si les données peuvent inclure des espaces, cela échouera. Envisagez de tester trim (champ), éventuellement avec un argument supplémentaire pour supprimer les nouvelles lignes.
Michael Grazebrook
les données sont numériques, vous pouvez également le faire: select ((field% 1) = 0);
ThiamTeck
Merci, mais pour la comparaison numérique, je pense que vous n'en avez pas besoin (strcmp (ceil (field), field))
Alan Dixon
14

Faites-le correspondre à une expression régulière.

cf http://forums.mysql.com/read.php?60,1907,38488#msg-38488 comme cité ci-dessous:

Re: Clause IsNumeric () dans MySQL ??
Posté par: kevinclark ()
Date: 08 août 2005 13:01


Je suis d'accord. Voici une fonction que j'ai créée pour 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]+)$';


Cela permet un signe plus / moins facultatif au début, un point décimal facultatif et les autres chiffres numériques.

JBB
la source
Merci, votre solution prend également en charge les décimales
Ananda
12

Supposons que nous ayons une colonne avec un champ alphanumérique ayant des entrées comme

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

et vous voulez la valeur numérique la plus élevée de cette colonne de base de données (dans ce cas, il s'agit de 9582), cette requête vous aidera

SELECT Max(column_name) from table_name where column_name REGEXP '^[0-9]+$'
Tarun Sood
la source
1
«10000» est plus élevé, mais votre requête renverra toujours «9582» .
Paul Spiegel
8

Voici la solution simple en supposant que le type de données est varchar

select * from calender where year > 0

Il retournera vrai si l'année est numérique sinon faux

Jayjitraj
la source
29
Dans un varchar, cela retournera également true si le premier caractère est numérique.
TuK
Je n'ai pas remarqué cela. voter pour votre commentaire :)
Jayjitraj
8

Cela fonctionne également:

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

par exemple

SELECT CAST('a123' AS UNSIGNED) // returns 0
SELECT CAST('123' AS UNSIGNED) // returns 123 i.e. > 0
Riad
la source
11
qu'en est-il SELECT CAST('12a34' AS UNSIGNED), qui revient 12?
Mike C
1
Cela fonctionne parfaitement si vous devez tester des éléments non numériques, cela mérite plus de +1. Les autres réponses sont plus difficiles à inverser le test pour trouver les éléments non numériques.
DrCord
1
@DrCord cela ne fonctionne pas pour le cas décrit par Mike C, donc très peu fiable
jontro
4

Pour vérifier si une valeur est Int dans Mysql, nous pouvons utiliser la requête suivante. Cette requête donnera les lignes avec des valeurs Int

SELECT col1 FROM table WHERE concat('',col * 1) = col;
minhas23
la source
Cela sélectionnera également des nombres non entiers (par exemple «3,5» ).
Paul Spiegel
4

Le meilleur que je puisse penser d'une variable est un int Est une combinaison avec les fonctions de MySQL CAST()et LENGTH().
Cette méthode fonctionnera sur les types de données chaînes, entiers, doubles / flottants.

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

voir la démo http://sqlfiddle.com/#!9/ff40cd/44

il échouera si la colonne a une valeur de caractère unique. si la colonne a une valeur 'A' alors Cast ('A' as UNSIGNED) sera évalué à 0 et LENGTH (0) sera 1. donc LENGTH (Cast ('A' as UNSIGNED)) = LENGTH (0) sera évalué à 1 = 1 => 1

Le vrai Waqas Malik a totalement oublié de tester ce cas. le patch est.

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;

Résultats

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

voir la démo

Raymond Nijland
la source
il échouera si la colonne a une valeur de caractère unique. si la colonne a une valeur 'A' alors Cast ('A' as UNSIGNED) sera évalué à 0 et LENGTH (0) sera 1. donc LENGTH (Cast ('A' as UNSIGNED)) = LENGTH (0) sera évalué à 1 = 1 => 1
Waqas Malik
Merci pour le commentaire selon lequel le cas n'a en effet pas été testé @WaqasMalik fonctionne et teste un correctif en ce moment .. quelque chose commeSELECT "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
C'est une solution tellement cool. Je pense que cela échoue pour les entiers négatifs, est-ce que cela change quelque chose de substantiel (dans les cas extrêmes) pour changer votre solution en entiers signés? J'ai testé en utilisant votre violon comme 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;Ce refactoring gère tous les cas ci-dessus, mais même mon ajustement ne gère pas -1.0 ou "-1". Encore une fois, une solution super cool.
spen.smith
3

Qu'en est-il de:

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

pour tester le numérique et le corrolaire:

WHERE table.field != "0" and CAST(table.field as SIGNED) = 0
Tom Auger
la source
1
CAST (table.field)! = 0 ne fonctionnera pas car il a besoin d'un type à convertir.
Riad du
Cela fonctionne parfaitement si vous devez tester des éléments non numériques, cela mérite plus de +1. Les autres réponses sont plus difficiles à inverser le test pour trouver les éléments non numériques.
DrCord
Cela ne fonctionne pas pour les nombres comme "0000", "0" (espace) et "7x" (qui est considéré comme un nombre).
Michael Grazebrook
@MichaelGrazebrook Je suppose que vous pourriez faire une expression régulière pour les deux premiers cas. "7x" est considéré comme un nombre? "0x7" est un nombre, mais 7x?
Tom Auger
1
@Tom Auger: Une autre réponse a porté sur les solutions de type regex. Ce que je voulais dire par «7x est considéré comme un nombre», c'est que cette affirmation est vraie: sélectionnez 7 = '7q'
Michael Grazebrook
1

J'ai essayé d'utiliser les expressions régulières répertoriées ci-dessus, mais elles ne fonctionnent pas pour les éléments suivants:

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

Ce qui précède retournera 1( TRUE), ce qui signifie que le test de la chaîne '12 INCHES 'par rapport à l'expression régulière ci-dessus, renvoie TRUE. Il ressemble à un nombre basé sur l'expression régulière utilisée ci-dessus. Dans ce cas, comme le 12 est au début de la chaîne, l'expression régulière l'interprète comme un nombre.

Ce qui suit retournera la bonne valeur (c'est-à-dire 0) car la chaîne commence par des caractères au lieu de chiffres

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

Ce qui précède retournera 0( FALSE) car le début de la chaîne est du texte et non numérique.

Cependant, si vous utilisez des chaînes contenant un mélange de chiffres et de lettres commençant par un nombre, vous n'obtiendrez pas les résultats souhaités. REGEXP interprétera la chaîne comme un nombre valide alors qu'en fait ce n'est pas le cas.

Bill Kelly
la source
2
Ceci est une erreur. L'avez-vous testé? Lorsque j'exécute votre premier exemple, il retourne FALSE, comme prévu, car l'expression régulière se termine par $ce qui signifie la fin de la chaîne, elle ne vérifie donc que les nombres, comme prévu par l'auteur.
spikyjt
1

Cela fonctionne bien pour VARCHAR où il commence par un nombre ou non.

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

peut avoir des restrictions lorsque vous accédez aux numéros NNNNE + - plus grands

PodTech.io
la source
Cela ne semble pas fonctionner pour les chaînes de caractères set @val = '5'; SELECT @val, concat('', @val * 1) != @val is_int;
simples
0

pour moi, la seule chose qui fonctionne est:

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

de kevinclark tous les autres me renvoient des trucs inutiles en cas de 234jk456ou12 inches

Tim
la source