Mladen Prajdić Blog

Blog about stuff and things and stuff. Mostly about SQL server and .Net

SQL Server: Filtering Numeric data from a character based column

Often you can see a request made by people to help them separate data in thier character based columns to numeric and non-numeric part.

Most often the answer they get is very simple: Use IsNumeric built in function.

But there's a very little known fact about this function though:

It DOES NOT behave the way you think it does!

You don't believe me? Let's see with an example. How many rows do you think this will return:

 

DECLARE @t1 TABLE (title varchar(20))
INSERT INTO @t1
SELECT '123d45' UNION ALL
SELECT '123e45' UNION ALL
SELECT '12 3456' UNION ALL
SELECT '123456' UNION ALL
SELECT '5532.673'

SELECT * FROM @t1 WHERE isnumeric(title) = 1

 

If you said 2 you're wrong. Run it. It return exactly 4 rows. You see IsNumeric returns 1 for every input that can be converted to

integer, floating point, money or decimal. This means that it also supports Scientific (E) notation.

In scientific notation 123D45 is 123*(10^45) in double precision and 123E45 is 123*(10^45) in single precision, which means that both are valid numbers.

 

I bet that right about now you're thinking: "I just want to filter my data!! Why does it have to be so complicated????" :))

No fear, the answer is here :).  This function will give you exactly what you need:

 

CREATE FUNCTION dbo.IsNumericEx( @value nvarchar(max) )
RETURNS BIT
AS
BEGIN
         DECLARE @isInt BIT
     <span class="kwrd">SELECT</span>  @isInt = 1 
     <span class="kwrd">WHERE</span>   @<span class="kwrd">value</span> <span class="kwrd">NOT</span> <span class="kwrd">LIKE</span> <span class="str">&#39;%[^0-9.-]%&#39;</span>
             <span class="kwrd">AND</span> LEN(REPLACE(@<span class="kwrd">value</span>, <span class="str">&#39;.&#39;</span>, <span class="str">&#39;&#39;</span>)) &gt;= LEN(@<span class="kwrd">value</span>) - 1
             <span class="kwrd">AND</span> CHARINDEX(<span class="str">&#39;-&#39;</span>, @<span class="kwrd">value</span>) <span class="kwrd">IN</span> (0, 1)
             <span class="kwrd">AND</span> CHARINDEX(<span class="str">&#39;-&#39;</span>, @<span class="kwrd">value</span>, 2) = 0

     <span class="kwrd">RETURN</span> ISNULL(@isInt, 0)

END GO

DECLARE @t1 TABLE (title varchar(20)) INSERT INTO @t1 SELECT '123d456' UNION ALL SELECT '12 3456' UNION ALL SELECT '123456' UNION ALL SELECT '1234-56' UNION ALL SELECT '123456-' UNION ALL SELECT '-123456' UNION ALL SELECT '-123-456' UNION ALL SELECT 'dddfaf56' UNION ALL SELECT '5532.673' UNION ALL SELECT '5532673.' UNION ALL SELECT '.5532.673'

SELECT * FROM @t1 WHERE dbo.IsNumericEx(title) = 0

SELECT * FROM @t1 WHERE dbo.IsNumericEx(title) = 1

GO DROP FUNCTION dbo.IsNumericEx

 

Enjoy it!

 

kick it on DotNetKicks.com
 

Legacy Comments


Jeff
2007-10-19
re: SQL Server: Filtering Numeric data from a character based column
Hi Mladen -- good stuff, but what about commas?

I usually find it is simple to replace 'e' and 'd' with 'x' or something like that before using isnumeric:

select title, isnumeric(replace(replace(title,'d','x'),'e','x')) as IsNumber
from @t1

Works pretty well.

Mladen
2007-10-19
re: SQL Server: Filtering Numeric data from a character based column
what about commas?? commas are irrelevant :))

seriously though if someone needs that check it can be easily added.

Rolf Thomassen
2007-10-30
re: SQL Server: Filtering Numeric data from a character based column
Commas er very important.
If you think outside the US.

Here in europe we use comma as decimal point, and decimal point as 1000mark
So we have to do code for testing on the comma and removing the dot. as the DOT is irellevant here.

Long live country standards... not..

Also same thing with Dateformat, it is the biggest problem with database coding..

Mladen
2007-10-30
re: SQL Server: Filtering Numeric data from a character based column
tell me about it... i am from europe :)

however all this is not a problem if you use parameters, which in reality is just wishfull
since there are tons and tons of legacy apps that don't use them. :)

Mladen
2007-10-30
re: SQL Server: Filtering Numeric data from a character based column
hehe, rant away :)))

Johny The Rip
2007-11-02
re: SQL Server: Filtering Numeric data from a character based column
guys,
where exactly is Europe? I know somewhere around north pole...

RobIII
2007-11-19
re: SQL Server: Filtering Numeric data from a character based column
I don't think using a function like this on a large dataset is something you'd want. But if you DO; I would try to 'shortcut' the function before executing all kinds of replaces etc.

In Pseudocode:

Function IsNumericEx(someNum)
If IsNumeric then
...code posted in this blogpost
else
return false
End Function

hamzah
2009-05-25
re: SQL Server: Filtering Numeric data from a character based column
hi all

i wanna to take the number after "dot" in decimal at SQLServer

for example

the decimal 1234.5 here i wanna just to got the number after "dot"
here it's 5

and thank advanced