Как мне проверить, является ли значение целым числом в MySQL?


124

Я вижу , что в MySQL есть Cast()и Convert()функция для создания целых чисел из значений, но есть ли способ , чтобы проверить, если значение является целым числом? Что-то вроде is_int()PHP - вот что я ищу.


2
так что, к сожалению, мы должны создать функцию is_int () в Mysql
— Юда Правира

Ответы:


216

Я предполагаю, что вы хотите проверить строковое значение. Один из хороших способов - это оператор REGEXP, сопоставляющий строку с регулярным выражением. Просто делай

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

это достаточно быстро. Если ваше поле числовое, просто проверьте

ceil(field) = field

вместо.


4
Тест 'ceil (field) = field' - хорошая идея, но, как указал @Jumpy, он не работает с нечисловыми данными: SELECT ceil ('four') = 'four'; -> 1
— Мэтью Корнелл

3
@MatthewCornell, Он сказал, если ваше поле числовое. Таким образом, вы можете проверить, является ли число целым. На струнах он не работает, поэтому есть первый вариант.
— Malfist

Если данные могут включать пробелы, это не сработает. Рассмотрите возможность тестирования trim (field), возможно, с дополнительным аргументом для удаления новой строки.
— Майкл Грейзбрук,

если данные числовые, тоже можно: select ((field% 1) = 0);
— ThiamTeck

Спасибо, но для числового сравнения, я думаю, вам не нужно (strcmp (ceil (field), field))
— Алан Диксон

14

Сопоставьте его с регулярным выражением.

cf http://forums.mysql.com/read.php?60,1907,38488#msg-38488, как указано ниже:

Re: Предложение IsNumeric () в MySQL ??
Автор: kevinclark ()
Дата: 8 августа 2005 г., 13:01


Я согласен. Вот функция, которую я создал для 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]+)$';


Это позволяет использовать необязательный знак плюс / минус в начале, одну необязательную десятичную точку и остальные числовые цифры.


Спасибо, ваше решение также заботится о десятичных дробях
— Ананда

12

Предположим, у нас есть столбец с буквенно-цифровым полем, в котором есть записи типа

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

и вам нужно наивысшее числовое значение из этого столбца db (в данном случае это 9582), тогда этот запрос поможет вам

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

1
«10000» больше, но ваш запрос все равно вернет «9582» .
— Пол Шпигель

8

Вот простое решение, предполагающее, что тип данных - varchar

select * from calender where year > 0

Он вернет true, если год числовой, иначе false


29
В varchar это также вернет истину, если первый символ числовой.
— TuK

Не заметил этого. голосование за ваш комментарий :)
— Jayjitraj

8

Это тоже работает:

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

например

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

11
как насчет того SELECT CAST('12a34' AS UNSIGNED), что возвращается 12?
— Mike C

1
Это отлично работает, если вам нужно проверить нечисловые элементы, это заслуживает большего количества +1. Другие ответы сложнее отменить тест, чтобы найти нечисловые элементы.
— DrCord 06

1
@DrCord, это не работает в случае, описанном Майком С, следовательно, очень ненадежно
— jontro

4

Чтобы проверить, является ли значение Int в Mysql, мы можем использовать следующий запрос. Этот запрос выдаст строки со значениями Int

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

Это также выберет нецелые числа (например, «3,5» ).
— Пол Шпигель

4

Лучшее, что я мог придумать для переменной, - это int. Это комбинация функций MySQL CAST()и LENGTH().
Этот метод будет работать со строками, целыми числами, типами данных double / float.

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

см. демонстрацию http://sqlfiddle.com/#!9/ff40cd/44

он завершится неудачно, если в столбце будет однозначное значение. если столбец имеет значение 'A', тогда Cast ('A' как UNSIGNED) будет оцениваться как 0, а LENGTH (0) будет равно 1. поэтому LENGTH (Cast ('A' as UNSIGNED)) = LENGTH (0) будет оцениваться как 1 = 1 => 1

Истинный Вакас Малик совершенно не хочет проверить этот случай. патч есть.

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;

Полученные результаты

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

см. демонстрацию


он завершится неудачно, если в столбце будет однозначное значение. если столбец имеет значение 'A', тогда Cast ('A' как UNSIGNED) будет оцениваться как 0, а LENGTH (0) будет равно 1. поэтому LENGTH (Cast ('A' as UNSIGNED)) = LENGTH (0) будет оцениваться как 1 = 1 => 1
— Вакас Малик

Спасибо за комментарий, этот случай действительно не был протестирован @WaqasMalik работает и тестирует патч прямо сейчас .. что-то вроде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;
— Raymond Nijland

Это такое классное решение. Я думаю, что это не работает для отрицательных целых чисел, меняет ли это что-нибудь существенное (в крайних случаях), чтобы переключить ваше решение на целые числа со знаком? Я тестировал вашу скрипку как основу. 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;Этот рефакторинг обрабатывает все вышеупомянутые случаи, но даже моя настройка не обрабатывает -1,0 или «-1». Опять же, супер крутое решение.
— spen.smith

3

Что о:

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

для проверки числовых значений и соответствий:

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

1
CAST (table.field)! = 0 не будет работать, так как ему требуется тип для приведения.
— Riad

Это отлично работает, если вам нужно проверить нечисловые элементы, это заслуживает большего количества +1. Другие ответы сложнее отменить тест, чтобы найти нечисловые элементы.
— DrCord 06

Это не работает для таких чисел, как «0000», «0» (пробел) и «7x» (которое считается числом).
— Майкл Грейзбрук,

@MichaelGrazebrook Я полагаю, вы могли бы сделать регулярное выражение для первых двух случаев. «7x» считается числом? «0x7» - это число, а 7x?
— Tom Auger

1
@Tom Auger: Другой ответ касался решений типа регулярных выражений. Под «7x считается числом» я имел в виду то, что это утверждение верно: select 7 = '7q'
— Майкл Грейзбрук

1

Я пробовал использовать перечисленные выше регулярные выражения, но они не работают в следующих случаях:

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

Вышеупомянутое будет return 1( TRUE), что означает, что проверка строки «12 ДЮЙМОВ» против регулярного выражения выше, возвращается TRUE. Это похоже на число, основанное на использованном выше регулярном выражении. В этом случае, поскольку 12 находится в начале строки, регулярное выражение интерпретирует его как число.

Следующее вернет правильное значение (т.е. 0), потому что строка начинается с символов вместо цифр.

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

Вышеупомянутое будет return 0( FALSE), потому что начало строки - текст, а не число.

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


2
Это неверно. Вы это тестировали? Когда я запускаю ваш первый пример, он возвращается FALSE, как и ожидалось, потому что регулярное выражение заканчивается, $что означает конец строки, поэтому он проверяет только числа, как задумано автором.
— spikyjt

1

Это хорошо работает для VARCHAR, где он начинается с числа или нет ..

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

могут иметь ограничения при переходе к большим номерам NNNNE +


Похоже, это не работает для одиночных символьных строкset @val = '5'; SELECT @val, concat('', @val * 1) != @val is_int;
— spen.smith

0

для меня единственное, что работает:

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

от kevinclark все остальные возвращают бесполезные вещи для меня в случае 234jk456или12 inches

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.