SQL IsNumeric function
472369326D4
is a valid float
type. The D4
is translated as adding four 0
values, effectively multiplying the value before the D
character by 10000
.
Example Sql
SELECT cast('472369326D4' as float)
SELECT cast('472369326D3' as float)
SELECT cast('472369326D2' as float)
Output:
4723693260000
472369326000
47236932600
SQL Server's ISNUMERIC function
Unfortunately, the ISNUMERIC()
function in SQL Server has many quirks. It's not exactly buggy, but it rarely does what people expect it to when they first use it.
However, since you're using SQL Server 2012 you can use the TRY_PARSE()
function which will do what you want.
This returns NULL:SELECT TRY_PARSE('7860D399' AS int)
This returns 7860399SELECT TRY_PARSE('7860399' AS int)
https://msdn.microsoft.com/en-us/library/hh213126.aspx
Obviously, this works for datatypes other than INT
as well. You say you want to check that a value is numeric, but I think you mean INT
.
SQL Server's ISNUMERIC function, with just a minus-sign
You can make a simple check:
;WITH cte AS (
SELECT 1 as num
UNION ALL
SELECT num+1
FROM cte
WHERE num< 256
)
SELECT num,
CHAR(num),
ISNUMERIC(CHAR(num))
FROM cte
WHERE ISNUMERIC(CHAR(num)) = 1
OPTION (MAXRECURSION 1000)
This will show that not only numbers are considered valid numeric type:
$
+
,
-
.
\
€
¤
One of the workarounds is to use NOT LIKE '%[^0-9]%'
F.e. if I add this nd CHAR(num) NOT LIKE '%[^0-9]%'
to WHERE statement of below query it will return numbers from 0 to 9
Or use TRY_PARSE(.. as int)
Some links:
https://msdn.microsoft.com/en-us/library/hh213126.aspx
http://www.sqlservercentral.com/articles/ISNUMERIC()/71512/
Efficient ISNUMERIC() replacements on SQL Server?
You can use the T-SQL functions TRY_CAST() or TRY_CONVERT() if you're running SQL Server 2012 as Bacon Bits mentions in the comments:
SELECT CASE WHEN TRY_CAST('foo' AS INT) IS NULL THEN 0 ELSE 1 END
SELECT CASE WHEN TRY_CAST(1 AS INT) IS NULL THEN 0 ELSE 1 END
If you're using SQL 2008 R2 or older, you'll have to use a .NET CLR function, and wrap System.Decimal.TryParse().
CAST and IsNumeric
IsNumeric returns 1 if the varchar value can be converted to ANY number type. This includes int, bigint, decimal, numeric, real & float.
Scientific notation could be causing you a problem. For example:
Declare @Temp Table(Data VarChar(20))
Insert Into @Temp Values(NULL)
Insert Into @Temp Values('1')
Insert Into @Temp Values('1e4')
Insert Into @Temp Values('Not a number')
Select Cast(Data as bigint)
From @Temp
Where IsNumeric(Data) = 1 And Data Is Not NULL
There is a trick you can use with IsNumeric so that it returns 0 for numbers with scientific notation. You can apply a similar trick to prevent decimal values.
IsNumeric(YourColumn + 'e0')
IsNumeric(YourColumn + '.0e0')
Try it out.
SELECT CAST(myVarcharColumn AS bigint)
FROM myTable
WHERE IsNumeric(myVarcharColumn + '.0e0') = 1 AND myVarcharColumn IS NOT NULL
GROUP BY myVarcharColumn
ISNUMERIC function with Tab char(9)
Not only Char(9),it does for all of the values below..
SELECT [Ascii Code] = STR(Number),
[Ascii Character] = CHAR(Number),
[ISNUMERIC Returns] = ISNUMERIC(CHAR(Number))
FROM Master.dbo.spt_Values
WHERE Type = 'P'
AND Number BETWEEN 0 AND 255
AND ISNUMERIC(CHAR(Number)) = 1
Ascii Code Ascii Character ISNUMERIC Returns
---------- --------------- -----------------
9 1
10 1
11 1
12 1
13 1
36 $ 1
43 + 1
44 , 1
45 - 1
46 . 1
48 0 1
49 1 1
50 2 1
51 3 1
52 4 1
53 5 1
54 6 1
From the Official docs..emphasis on highlighted..
ISNUMERIC returns 1 when the input expression evaluates to a valid integer, floating point number, money or decimal type; otherwise it returns 0. A return value of 1 guarantees that expression can be converted to one of these numeric types
So Isnumeric will return 1 if it returns any one of the type in highlighted part above..
Jeff moden Describes the why part here..
There are many different combinations of letters, numbers, and symbols that can actually be converted to numeric data types and ISNUMERIC will return a "1" for all of them. It's not a flaw... that's the way it's supposed to work!
References:
http://www.sqlservercentral.com/articles/ISNUMERIC()/71512/
SQL Server ISNUMERIC() Clarification
You should use CAST()
or TRY_CAST()
instead:
declare @test nvarchar(8) = '12345678'
select cast(@test as bigint) -- errors on failure
select try_cast(@test as bigint) -- returns null on failure
Also, important to point out the ISNUMERIC()
isn't perfect. From the docs:
ISNUMERIC returns 1 for some characters that are not numbers, such as plus (+), minus (-), and valid currency symbols such as the dollar sign ($). For a complete list of currency symbols, see money and smallmoney (Transact-SQL).
For this reason I don't think the logical check is of value here. Best to use TRY_CAST()
on all values, regardless of the presence of characters and handle the null response in a predictable manner.
Why ISNumeric() Transact-SQL function treats some var-chars as Int
ISNUMERIC()
has some flaws. It can return True/1 for values that are clearly not numbers.
SELECT
ISNUMERIC('.'),
ISNUMERIC('$')
If this is causing you issues, try using TRY_PARSE()
SELECT
TRY_PARSE('2' AS INT)
You can use this and filter for non-null results.
SELECT some_column
FROM some_table
WHERE TRY_PARSE(some_column AS INT) IS NOT NULL
Related Topics
Foreign Keys - What Do They Do for Me
How to Split Comma Separated String Inside Stored Procedure
Using Guid in SQLite Select Where Guid Is Stored in the SQLite Db as Binaries
How to Run SQL Server Stored Procedures in Parallel
How to Select All Hours Between Two Dates
Sql: Sort by Priority, But Put 0 Last
Do You Prefer Verbose Naming When It Comes to Database Columns
Sql: Retrieve Only the Records Whose Value Has Changed
How to Get Age in Years,Months and Days Using Oracle
Postgres SQL 'Could Not Determine Data Type of Parameter' by Hibernate
Oracle SQL - Add Primary Key to Table
Max Row Size in SQL Server 2012 with Varchar(Max) Fields
SQL Azure: What Will Happen If Size of My SQL Azure Get 5Gb