Como verifico se um valor é um número inteiro no MySQL?

122

Vejo que dentro MySQL existem Cast()e Convert()funções para criar inteiros de valores, mas existe alguma maneira de verificar se um valor é um inteiro? Algo como is_int()no PHP é o que estou procurando.

Craig Nakamoto
fonte
2
tão tristemente devemos criar is_int () função no MySQL
Yuda Prawira

Respostas:

213

Suponho que você deseja verificar um valor de sequência. Uma boa maneira é o operador REGEXP, correspondendo a string a uma expressão regular. Simplesmente faça

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

isso é razoavelmente rápido. Se o seu campo for numérico, apenas teste para

ceil(field) = field

em vez de.

Jumpy
fonte
4
O teste 'ceil (campo) = campo' é uma boa idéia, mas como @Jumpy apontou, ele falha em dados não numéricos: SELECT ceil ('four') = 'four'; -> 1
Matthew Cornell
2
@ MatthewCornell, ele disse se o seu campo é numérico. É assim que você pode testar se um número é um número inteiro. Não funciona em strings, é por isso que a primeira opção está lá.
Malfist
Se os dados incluírem espaço em branco, isso falhará. Considere testar o ajuste (campo), possivelmente com um argumento extra para remover novas linhas.
Michael Grazebrook
os dados são numéricos, também é possível: select ((campo% 1) = 0);
ThiamTeck
Obrigado, mas para a comparação numérica, acho que você não precisa (strcmp (ceil (campo), campo))
Alan Dixon
14

Combine-o com uma expressão regular.

cf http://forums.mysql.com/read.php?60,1907,38488#msg-38488 conforme citado abaixo:

Re: IsNumeric () cláusula no MySQL?
Publicado por: kevinclark ()
Data: 08 de agosto de 2005 13:01


Concordo. Aqui está uma função que eu criei para o 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]+)$';


Isso permite um sinal de mais / menos opcional no início, um ponto decimal opcional e os dígitos numéricos restantes.

JBB
fonte
Obrigado, sua solução cuida de decimais também
Ananda
12

Suponha que tenhamos coluna com campo alfanumérico com entradas como

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

e você deseja o valor numérico mais alto dessa coluna db (nesse caso, é 9582), essa consulta o ajudará

SELECT Max(column_name) from table_name where column_name REGEXP '^[0-9]+$'
Tarun Sood
fonte
1
'10000' é maior, mas sua consulta ainda retornaria '9582' .
Paul Spiegel
8

Aqui está a solução simples, assumindo que o tipo de dados é varchar

select * from calender where year > 0

Ele retornará verdadeiro se o ano for numérico ou falso

Jayjitraj
fonte
29
Em um varchar, isso também retornará true se o primeiro caractere for numérico.
tuk
Não percebi isso. up-voto o seu comentário :)
Jayjitraj
8

Isso também funciona:

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

por exemplo

SELECT CAST('a123' AS UNSIGNED) // returns 0
SELECT CAST('123' AS UNSIGNED) // returns 123 i.e. > 0
Riad
fonte
11
e quanto SELECT CAST('12a34' AS UNSIGNED), que retorna 12?
Mike C
1
Isso funciona perfeitamente se você precisar testar itens não numéricos, pois isso merece mais +1. As outras respostas são mais difíceis de reverter o teste para encontrar os itens não numéricos.
DrCord
1
@DrCord isso não funciona para o caso Mike C descrito, portanto, é muito pouco confiável
jontro
4

Para verificar se um valor é Int no Mysql, podemos usar a seguinte consulta. Esta consulta fornecerá as linhas com valores Int

SELECT col1 FROM table WHERE concat('',col * 1) = col;
minhas23
fonte
Isso também selecionará números não inteiros (por exemplo, '3,5' ).
Paul Spiegel
4

O melhor que eu poderia pensar em uma variável é int. É uma combinação com as funções CAST()e MySQL LENGTH().
Este método funcionará em tipos de dados strings, inteiros, duplos / flutuantes.

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

veja a demonstração http://sqlfiddle.com/#!9/ff40cd/44

falhará se a coluna tiver um valor de caractere único. se a coluna tiver um valor 'A', a conversão ('A' como NÃO ASSINADO) será avaliada como 0 e COMPRIMENTO (0) será 1. assim, COMPRIMENTO (conversão ('A' como NÃO ASSINADO)) = COMPRIMENTO (0) avaliará como 1 = 1 => 1

O verdadeiro Waqas Malik conseguiu escapar totalmente desse teste. o 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;

Resultados

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

veja demonstração

Raymond Nijland
fonte
falhará se a coluna tiver um valor de caractere único. se a coluna tiver um valor 'A', a conversão ('A' como NÃO ASSINADO) será avaliada como 0 e COMPRIMENTO (0) será 1. assim, COMPRIMENTO (conversão ('A' como NÃO ASSINADO)) = COMPRIMENTO (0) avaliará como 1 = 1 => 1
Waqas Malik
Obrigado pelo comentário nesse caso era realmente testado @WaqasMalik trabalhando e testando uma correção agora .. algo comoSELECT "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
Esta é uma solução tão legal. Eu acho que falha em números inteiros negativos, isso muda alguma coisa substantiva (em casos extremos) para mudar sua solução para números inteiros assinados? Eu tenho testado usando seu violino como 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;Essa refatoração lida com todos os casos acima, mas mesmo meu ajuste não lida com -1,0 ou '-1'. Mais uma vez, uma solução super legal.
spen.smith 26/06
3

A respeito:

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

para testar o numérico e o corrolário:

WHERE table.field != "0" and CAST(table.field as SIGNED) = 0
Tom Auger
fonte
1
CAST (table.field)! = 0 não funcionará, pois precisa de um tipo para converter.
Riad
Isso funciona perfeitamente se você precisar testar itens não numéricos, pois isso merece mais +1. As outras respostas são mais difíceis de reverter o teste para encontrar os itens não numéricos.
DrCord
Isso não funciona para números como "0000", "0" (espaço) e "7x" (que é considerado um número).
Michael Grazebrook
@MichaelGrazebrook Suponho que você possa fazer uma regexp para os dois primeiros casos. "7x" é considerado um número? "0x7" é um número, mas 7x?
Tom Auger
1
@ Tom Auger: Outra resposta abordou as soluções do tipo regex. O que eu quis dizer com "7x é considerado um número" é que esta afirmação é verdadeira: selecione 7 = '7q'
Michael Grazebrook 18/03/2015
1

Tentei usar as expressões regulares listadas acima, mas elas não funcionam para o seguinte:

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

O exemplo acima retornará 1( TRUE), o que significa que o teste da string '12 INCHES 'contra a expressão regular acima retorna TRUE. Parece um número com base na expressão regular usada acima. Nesse caso, como o 12 está no início da sequência, a expressão regular a interpreta como um número.

A seguir, retornará o valor correto (ou seja 0) porque a sequência começa com caracteres em vez de dígitos

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

O acima retornará 0(FALSE ) porque o início da string é texto e não numérico.

No entanto, se você estiver lidando com seqüências de caracteres com uma mistura de números e letras que começam com um número, não obterá os resultados desejados. REGEXP interpretará a seqüência de caracteres como um número válido quando, na verdade, não é.

Bill Kelly
fonte
2
Isto está incorreto. Você testou? Quando executo o seu primeiro exemplo, ele retorna FALSE, como esperado, porque o regex termina com o $que significa o fim da string, portanto, ele verifica apenas números, conforme pretendido pelo autor.
spikyjt 31/07
1

Isso funciona bem para o VARCHAR, onde começa com um número ou não.

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

pode ter restrições quando você obtém números NNNNE + maiores

PodTech.io
fonte
Isso parece não funcionar para strings de caracteres únicosset @val = '5'; SELECT @val, concat('', @val * 1) != @val is_int;
spen.smith
0

para mim, a única coisa que funciona é:

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 todas as outras coisas inúteis retorno para mim em caso de 234jk456ou12 inches

Tim
fonte