Определить, является ли значение числом в MySQL

159

Есть ли способ определить, является ли значение числом в запросе MySQL? Такие как

SELECT * 
FROM myTable 
WHERE isANumber(col1) = true
Urbycoz
источник
Я проверил стратегию 1 * col = col, но почему-то она терпит неудачу, когда запрос вызывается через PHP (возвращая true, когда это не должно). В phpMyAdmin однако взлом работает. Это означает, что мой тест ведет себя как ожидалось, покупка моего приложения - нет.
Джахазиил

Ответы:

251

Это должно работать в большинстве случаев.

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

Это не работает для нестандартных номеров, таких как

  • 1e4
  • 1.2e5
  • 123. (конечный десятичный)
RichardTheKiwi
источник
Спасибо. К сожалению, мне нужно признать, что 123 - это число, а 123X - нет.
Urbycoz
1
@ Ричард, я только что прочитал твои исключения. Думал, ты имел в виду символ "е". Теперь я понимаю, что вы имеете в виду.
Urbycoz
Лидирующие нули не являются проблемой для ловкого разработчика sql --- trim (ведущий 0 из col1)
pimbrouwers
Я знаю, что это старый пост, но я использую этот метод в своем запросе. Но у меня есть проблема, он обнаруживает «2-Power» как «2», вызывая проблемы, поскольку он не должен этого делать. Любая идея ?
GRosay
1
Для конечных и ведущих нулей (например, 023.12000): concat ('', col1 * 1) = '0' ИЛИ ​​concat ('', col1 * 1) = IF (LOCATE ('.', Col1), TRIM (ОБА) 0 'ОТ col1), TRIM (ВЕДУЩИЙ' 0 'ОТ col1));
Франсуа Бретон
299

Вы также можете использовать регулярные выражения ... это будет выглядеть так:

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

Ссылка: http://dev.mysql.com/doc/refman/5.1/en/regexp.html

Т. Корнер
источник
70
SELECT * FROM myTable WHERE col1 REGEXP '^ [0-9] + $';
Дмитрий Козьменко
7
Принятый ответ действительно умный, но этот ответ более прямой, и я думаю, что это должно быть принятое решение.
Pedromanoel
21
Для случая «не совпадает»: WHERE col1 NOT REGEXP...и для случая, когда вы можете иметь десятичную точку, используйте регулярное выражение:^[0-9\.]+$
Робби Аверилл
2
Также не работает для научной нотации, работает только для целых
Дэвид Уилкинс
1
Regex migth будет трудно читать людям, которые никогда не использовали его, но вы можете делать с ним действительно хорошие и короткие вещи
Olli
56

Если ваши данные «test», «test0», «test1111», «111test», «111»

Чтобы выбрать все записи, где данные являются простыми int:

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

Результат: '111'

(В регулярном выражении ^ означает начало, а $ означает конец)

Чтобы выбрать все записи, в которых существует целое или десятичное число:

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

Результат: «111» (аналогично последнему примеру)

Наконец, чтобы выбрать все записи, где существует номер, используйте это:

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

Результат: «test0» и «test1111» и «111test» и «111»

Дмитрий Козьменко
источник
Мне нравится этот подход лучше, потому что он более четкий и менее "хакерский", чем трюк с конкатенацией. Спасибо!
brokethebuildagain
8
Не работает для отрицательных значений. Я бы исправил предложенное регулярное выражение следующим образом:REGEXP '^[+\-]?[0-9]+\\.?[0-9]*$'
Николас
Я бы сказал, что символ «+» не является необходимым, вы можете использовать только «-?», Но если вы хотите использовать его, вы должны его избежать (и символ «-» не нужно экранировать) ,
Т. Корнер
13
SELECT * FROM myTable
WHERE col1 REGEXP '^[+-]?[0-9]*([0-9]\\.|[0-9]|\\.[0-9])[0-9]*(e[+-]?[0-9]+)?$'

Также будет соответствовать десятичным знакам со знаком (например, -1.2, +0.2, 6., 2e9, 1.2e-10 ).

Тест:

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;

Результат:

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

демонстрация

Пол Шпигель
источник
3
Отлично! Единственный ответ, который на самом деле охватывает все основания. Должен быть принятый ответ.
Дом
10

Возвращает числовые строки

Я нашел решение с помощью следующего запроса и работает для меня:

SELECT * FROM myTable WHERE col1 > 0;

Этот запрос возвращает строки, имеющие только столбец с номерами больше нуля, которые col1

Возвращает нечисловые строки

если вы хотите проверить столбец не числовой, попробуйте этот с помощью трюка ( !col1 > 0):

SELECT * FROM myTable WHERE !col1 > 0;
бора
источник
Это не работает, если у вас есть строка, которая начинается с цифры «123abc», она будет возвращена в вашем выражении с числовыми строками, а не в нечисловом выражении.
Стефен
@JStephen Ты прав! Поскольку SELECT * FROM myTable WHERE col1 = 123;запрос будет возвращать строки, даже значение столбца123abc
Bora
9

Этот ответ похож на Дмитрия, но он допускает десятичные, а также положительные и отрицательные числа.

select * from table where col1 REGEXP '^[[:digit:]]+$'
Devpaq
источник
8

использовать UDF (пользовательская функция).

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

Затем, когда вы запрашиваете

select isnumber('383XXXX') 

- возвращает 0

select isnumber('38333434') 

- возвращает 1

выберите isnumber (mycol) mycol1, col2, colx из таблицы; - вернет 1 и 0 для столбца mycol1

- Вы можете улучшить функцию, чтобы принимать десятичные дроби, научные записи и т. д ...

Преимущество использования UDF заключается в том, что вы можете использовать его слева или справа от сравнения «где предложение». это значительно упрощает ваш SQL перед отправкой в ​​базу данных:

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

надеюсь это поможет.

Хьюго Р
источник
5

Еще одна альтернатива, которая кажется быстрее чем REGEXP на моем компьютере:

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

Это выберет все строки, где col1 начинается с числового значения.

Стиан Хватум
источник
2
А что если значение равно нулю?
Urbycoz
1
Я думаю, вы могли бы просто добавить, AND col1<>0чтобы обработать это исключение.
Urbycoz
Это правда, что он не работает для нулевых значений, но он отлично работает для дополненных чисел, например, 004. Принятый ответ не работает для дополненных чисел
Аббас
Я думаю, что это лучший способ проверить номера. Просто нам нужно добавить оператор OR для проверки нуля, как SELECT * FROM myTable WHERE col1 * 0! = Col1 OR col1 = '0';
Бину Раман
Я получаю ложное срабатывание '1a'. Кстати: это эквивалентно WHERE col1 <> 0- rextester.com/DJIS1493
Пол Шпигель
4

Все еще отсутствует эта простая версия:

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

(сложение должно быть быстрее по мере умножения)

Или самая медленная версия для дальнейшей игры:

SELECT *, 
CASE WHEN `col1` + 0 = `col1` THEN 1 ELSE 0 END AS `IS_NUMERIC` 
FROM `myTable`
HAVING `IS_NUMERIC` = 1
Йирка Копржива
источник
3
Если я не понимаю, MySQL преобразует любую строку в 0, так что это не будет различать строки и числа, оба будут возвращать одно и то же.
Иван
3
'a' + 0 = 'a'ИСТИНА
Пол Шпигель
3

Я рекомендую: если ваш поиск прост, вы можете использовать `

column*1 = column

Оператор интересный :) работает и быстрее чем на полях varchar / char

SELECT * FROM myTable WHERE column * 1 = столбец;

ABC*1 => 0 (NOT EQU **ABC**)
AB15*A => 15 (NOT EQU **AB15**)
15AB => 15 (NOT EQU **15AB**)
15 => 15 (EQUALS TRUE **15**)
Ferhat KOÇER
источник
1
Вы знаете , что в MySQL как select 'aaa123' >= 0и select '123aaa' >= 0возвращает истину?
Гжегож Смулько
1
SELECT * FROM myTable WHERE sign (col1)!=0

ofcourse sign (0) равен нулю, но тогда вы можете ограничить свой запрос ...

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

ОБНОВЛЕНИЕ: Это не на 100% надежно, потому что «1abc» вернул бы знак 1, но «ab1c» вернул бы ноль ... так что это может работать только для текста, который не начинается с цифр.

Miguel
источник
0

вы можете сделать с помощью CAST

  SELECT * from tbl where col1 = concat(cast(col1 as decimal), "")
Sumit
источник
0

Я обнаружил, что это работает довольно хорошо

if(col1/col1= 1,'number',col1) AS myInfo
Майк Эльф
источник
Это то же самое, что проверить col1 <> 0и дает ложный положительный результат для 1a- rextester.com/HLORBZ1242
Пол Шпигель
-1

Попробуйте разделить / 1

select if(value/1>0 or value=0,'its a number', 'its not a number') from table
Диего Гвидобоно
источник