142

I see that within MySQL there are Cast() and Convert() functions to create integers from values, but is there any way to check to see if a value is an integer? Something like is_int() in PHP is what I am looking for.

Chetan Gawai
  • 2,361
  • 1
  • 25
  • 36
Craig Nakamoto
  • 2,075
  • 2
  • 18
  • 19

11 Answers11

245

I'll assume you want to check a string value. One nice way is the REGEXP operator, matching the string to a regular expression. Simply do

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

this is reasonably fast. If your field is numeric, just test for

ceil(field) = field

instead.

Jumpy
  • 3,437
  • 1
  • 17
  • 4
  • 4
    The 'ceil(field) = field' test is a nice idea, but as @Jumpy pointed out, it fails on non-numeric data: SELECT ceil('four') = 'four'; -> 1 – Matthew Cornell Jul 17 '13 at 16:23
  • 7
    @MatthewCornell, He said if your field is numeric. That's so you can test if a number is an integer. It won't work on strings, that's why the first option is there. – Malfist Oct 25 '13 at 20:53
  • If the data might include whitespace, this would fail. Consider testing trim(field), possibly with an extra arg to remove newlines. – Michael Grazebrook Mar 11 '15 at 18:44
  • the the data is numeric, may do this too: select ((field % 1) = 0); – ThiamTeck May 06 '16 at 02:29
  • Thanks, but for the numeric comparison, I think you need not(strcmp(ceil(field),field)) – Alan Dixon Apr 06 '17 at 19:08
15

Match it against a regular expression.

c.f. http://forums.mysql.com/read.php?60,1907,38488#msg-38488 as quoted below:

Re: IsNumeric() clause in MySQL??
Posted by: kevinclark ()
Date: August 08, 2005 01:01PM


I agree. Here is a function I created for 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]+)$';


This allows for an optional plus/minus sign at the beginning, one optional decimal point, and the rest numeric digits.

Community
  • 1
  • 1
JBB
  • 4,543
  • 3
  • 24
  • 25
14

Suppose we have column with alphanumeric field having entries like

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

and you want highest numeric value from this db column (in this case it is 9582) then this query will help you

SELECT Max(column_name) from table_name where column_name REGEXP '^[0-9]+$'
fancyPants
  • 50,732
  • 33
  • 89
  • 96
Tarun Sood
  • 141
  • 1
  • 2
8

This also works:

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

for example

SELECT CAST('a123' AS UNSIGNED) // returns 0
SELECT CAST('123' AS UNSIGNED) // returns 123 i.e. > 0
Riad
  • 3,822
  • 5
  • 28
  • 39
  • 12
    what about `SELECT CAST('12a34' AS UNSIGNED)`, which returns `12`? – Mike C Jun 03 '14 at 15:07
  • 1
    This works perfect if you need to test for non-numeric items, this deserves more +1s. The other answers are harder to reverse the test to find the non-numeric items. – DrCord Aug 06 '14 at 16:02
  • 1
    @DrCord this does not work for the case Mike C described, hence is very unreliable – jontro Dec 13 '17 at 16:24
8

Here is the simple solution for it assuming the data type is varchar

select * from calender where year > 0

It will return true if the year is numeric else false

Pascal MARTIN
  • 395,085
  • 80
  • 655
  • 663
Jayjitraj
  • 236
  • 2
  • 12
6

To check if a value is Int in Mysql, we can use the following query. This query will give the rows with Int values

SELECT col1 FROM table WHERE concat('',col * 1) = col;
minhas23
  • 9,291
  • 3
  • 58
  • 40
5

The best i could think of a variable is a int Is a combination with MySQL's functions CAST() and LENGTH().
This method will work on strings, integers, doubles/floats datatypes.

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

see demo http://sqlfiddle.com/#!9/ff40cd/44

it will fail if the column has a single character value. if column has a value 'A' then Cast('A' as UNSIGNED) will evaluate to 0 and LENGTH(0) will be 1. so LENGTH(Cast('A' as UNSIGNED))=LENGTH(0) will evaluate to 1=1 => 1

True Waqas Malik totally fogotten to test that case. the patch is.

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;

Results

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

see demo

Raymond Nijland
  • 11,488
  • 2
  • 22
  • 34
  • it will fail if the column has a single character value. if column has a value 'A' then Cast('A' as UNSIGNED) will evaluate to 0 and LENGTH(0) will be 1. so LENGTH(Cast('A' as UNSIGNED))=LENGTH(0) will evaluate to 1=1 => 1 – Waqas Malik Jan 17 '19 at 11:41
  • Thanks for the comment that case was indeed untested @WaqasMalik working and testing a patch right now.. something like `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 Jan 17 '19 at 13:28
  • This is such a cool solution. I think it fails for negative integers, does it change anything substantive (in edge cases) to switch your solution to signed integers? I've been testing using your fiddle as the 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;` This refactoring handles all above cases, but even my adjustment doesn't handle -1.0 or '-1.' Again, a super cool solution. – spen.smith Jun 26 '20 at 05:14
  • thanks for the positive and kind words @spen.smith not tested fully but try with ABS() -> https://www.db-fiddle.com/f/NNXJ9cPwxjNPz9NknsSGU/3 – Raymond Nijland Sep 06 '20 at 08:01
3

What about:

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

to test for numeric and the corrolary:

WHERE table.field != "0" and CAST(table.field as SIGNED) = 0
Tom Auger
  • 19,421
  • 22
  • 81
  • 104
  • 1
    CAST(table.field) != 0 will not work as it needs a type to cast. – Riad Dec 24 '13 at 12:37
  • This works perfect if you need to test for non-numeric items, this deserves more +1s. The other answers are harder to reverse the test to find the non-numeric items. – DrCord Aug 06 '14 at 16:02
  • This doesn't work for numbers like "0000", " 0" (space) and "7x" (which is considered a number). – Michael Grazebrook Mar 11 '15 at 18:41
  • @MichaelGrazebrook I suppose you could do a regexp for the first two cases. "7x" is considered a number? "0x7" is a number, but 7x? – Tom Auger Mar 17 '15 at 20:52
  • 1
    @Tom Auger: Another answer covered the regex type solutions. What I meant by "7x is considered a number" is that this statement is true: select 7 = '7q' – Michael Grazebrook Mar 18 '15 at 10:59
1

I have tried using the regular expressions listed above, but they do not work for the following:

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

The above will return 1 (TRUE), meaning the test of the string '12 INCHES' against the regular expression above, returns TRUE. It looks like a number based on the regular expression used above. In this case, because the 12 is at the beginning of the string, the regular expression interprets it as a number.

The following will return the right value (i.e. 0) because the string starts with characters instead of digits

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

The above will return 0 (FALSE) because the beginning of the string is text and not numeric.

However, if you are dealing with strings that have a mix of numbers and letters that begin with a number, you will not get the results you want. REGEXP will interpret the string as a valid number when in fact it is not.

eeerahul
  • 1,629
  • 4
  • 27
  • 38
Bill Kelly
  • 19
  • 1
  • 2
    This is incorrect. Did you test it? When I run your first example, it returns `FALSE`, as expected, because the regex ends with `$` which means the end of the string, so it is checking for only numbers, as intended by the author. – spikyjt Jul 31 '14 at 11:19
1

This works well for VARCHAR where it begins with a number or not..

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

may have restrictions when you get to the larger NNNNE+- numbers

PodTech.io
  • 4,874
  • 41
  • 24
  • This doesn't seem to work for single char strings `set @val = '5'; SELECT @val, concat('', @val * 1) != @val is_int;` – spen.smith Jun 26 '20 at 04:58
0

for me the only thing that works is:

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

from kevinclark all other return useless stuff for me in case of 234jk456 or 12 inches

Lorenzo Belfanti
  • 1,205
  • 3
  • 25
  • 51
Tim
  • 1