Как мне проверить, является ли значение целым числом в 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.