Визначте, чи значення є числом у MySQL


159

Чи є спосіб визначити, чи є значення числом у запиті MySQL? Як от

SELECT * 
FROM myTable 
WHERE isANumber(col1) = true

Я перевірив стратегію 1 * col = col, але якимось чином виходить з ладу, коли запит викликається через PHP (повертає істину, коли не повинен). Однак у phpMyAdmin хак працює. Це означає, що мій тест поводиться так, як очікувалося. Придбати мою програму не потрібно.
— Jahaziel

Відповіді:


250

Це повинно працювати в більшості випадків.

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

Це не працює для нестандартних номерів, як-от

  • 1e4
  • 1.2e5
  • 123. (кінцевий десятковий)

Дякую. На жаль, мені це потрібно, щоб визнати, що 123 - це число, але 123X - це не так.
— Урбікоз

1
@ Річард, я просто прочитав винятки, які ви дали. Думав, ти мав на увазі персонажа "е". Я бачу, що ти маєш на увазі зараз.
— Урбікоз

Провідні нулі не є проблемою для розробника спритного sql --- обробка (ведуча 0 від col1)
— pimbrouwers

Я знаю, що це стара публікація, але я використовую цей метод у своєму запиті. Але у мене проблема, вона виявляє "2-Power" як "2", що спричиняє неприємності, оскільки цього не слід робити. Будь-яка ідея?
— GRosay

1
Для останнього та ведучого нулів (наприклад, 023.12000): concat ('', col1 * 1) = '0' АБО concat ('', col1 * 1) = IF (LOCATE ('.', Col1), TRIM (BOTH ' 0 'ВІД col1), TRIM (ЛІДИНГ' 0 'ВІД col1));
— Франсуа Бретон

299

Ви також можете використовувати Regular Expression ... це було б так:

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

Довідка: http://dev.mysql.com/doc/refman/5.1/en/regexp.html


70
ВИБІР * ІЗ myTable WHERE col1 REGEXP '^ [0-9] + $';
— Дмитро Козьменко

7
Прийнята відповідь дійсно розумна, але ця відповідь є більш прямою, і я думаю, це має бути прийнятим рішенням.
— pedromanoel

21
У випадку "не відповідає": WHERE col1 NOT REGEXP...а для випадку, коли у вас може бути десяткова крапка, використовуйте регулярний вираз:^[0-9\.]+$
— Роббі Аверилл

2
Також не працюватиме для наукових позначень, працює лише для інтів
— Девід Уілкінс

1
Людям, які ніколи не користувалися Regex migth, важко читати, але ви можете робити з ним справді чудові та короткі речі
— Оллі,

56

Якщо ваші дані 'test', 'test0', 'test1111', '111test', '111'

Щоб вибрати всі записи, де дані є простим цілим:

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

@JStephen Ви праві! Оскільки SELECT * FROM myTable WHERE col1 = 123;запит поверне рядки, рівне значення знаку123abc
— Bora

9

Ця відповідь схожа на Дмитра, але вона дозволить робити десяткові числа, а також додатні та від’ємні числа.

select * from table where col1 REGEXP '^[[:digit:]]+$'

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

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

- ви можете вдосконалити функцію прийому десяткових знаків, наукових позначень тощо ...

Перевага використання UDF полягає в тому, що ви можете використовувати його в лівій або правій частині порівняння "де застереження". це значно спрощує ваш SQL перед відправкою в базу даних:

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

сподіваюся, що це допомагає.


5

Ще одна альтернатива, яка здається швидшою, ніж REGEXP на моєму комп’ютері, - це

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

Це дозволить вибрати всі рядки, де col1 починається з числового значення.


2
А як бути, якщо значення дорівнює нулю?
— Урбікоз

1
Я думаю, ви можете просто додати, AND col1<>0щоб обробити цей виняток.
— Урбікоз

Це правда, що вона не працює для нульових значень, але вона прекрасно працює для прокладених чисел, наприклад, 004. Прийнята відповідь не працює для прокладених чисел
— Аббас,

Я думаю, що це найкращий спосіб перевірити наявність чисел. Просто нам потрібно додати оператор АБО для перевірки нуля, як SELECT * FROM myTable WHERE col1 * 0! = Col1 OR col1 = '0';
— Біну Раман

Я отримую помилковий позитив для '1a'. BTW: це рівнозначно 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

ВИБІР * ІЗ myTable WHERE стовпчик * 1 = стовпець;

ABC*1 => 0 (NOT EQU **ABC**)
AB15*A => 15 (NOT EQU **AB15**)
15AB => 15 (NOT EQU **15AB**)
15 => 15 (EQUALS TRUE **15**)

1
Чи знаєте ви, що в MySQL як select 'aaa123' >= 0і select '123aaa' >= 0повернути істину?
— Grzegorz Smulko

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

Знак курсу (0) дорівнює нулю, але тоді ви можете обмежити запит на ...

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

ОНОВЛЕННЯ: Це не на 100% надійно, тому що "1abc" поверне знак 1, але "ab1c" поверне нуль ... так що це може працювати лише для тексту, який не починається з цифр.


0

ви можете за допомогою CAST

  SELECT * from tbl where col1 = concat(cast(col1 as decimal), "")


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.