Login or Sign Up to become a member!
LessThanDot Sit Logo

LessThanDot

Data Management

Less Than Dot is a community of passionate IT professionals and enthusiasts dedicated to sharing technical knowledge, experience, and assistance. Inside you will find reference materials, interesting technical discussions, and expert tips and commentary. Once you register for an account you will have immediate access to the forums and all past articles and commentaries.

LTD Social Sitings

Lessthandot twitter Lessthandot Linkedin Lessthandot friendfeed Lessthandot facebook Lessthandot rss

Note: Watch for social icons on posts by your favorite authors to follow their postings on these and other social sites.

Your profile

    Search

    XML Feeds

    Google Ads

    « Including an Aggregated Column's Related ValuesOperand type clash: date is incompatible with int error when trying to do +1 on a date data type in SQL Server 2008 »
    comments

    Occasionally, it's necessary to convert character data (char, nchar, varchar, nvarchar) to a number. Before doing so, it is best to make sure that the value can be converted to a number.

    IsNumeric would be the obvious choice, but has some problems because it allows for unexpected characters during the conversion. For example, the following strings will return true from the IsNumeric function.

    $12.09
    1.4e3
    2d4

    Technically, all of these are numbers.

    1. Select Convert(Money, '$12.09')
    2. Select Convert(Float, '1.4e3')
    3. Select Convert(Float, '2d4')

    Often times, we don't want to allow the dollar sign or scientific notation.

    To make sure a value can be converted to an integer, you can append .0e0 to the end of the string before checking. If the original value had a decimal point, then adding another decimal point will cause the value to not be numeric. Similarly, adding e0 to a value that is already expressed in scientific notation will cause IsNumeric to return false.

    Consider the following values:

    Original   + '.0e0'    + 'e0'
    --------   ----------  --------
    $12.09     $12.09.0e0  $12.09e0
    1.4e3      1.4e3.0e0   1.4e3e0
    2d4        2d4.0e0     2d4e0
    3.7        3.7.0e0     3.7e0
    412        412.0e0     412e0

    Notice how the second column will only evaluate to true for the value that can be converted to an integer. Also notice how the 3rd column will only evaluate to true for the last 2 values.

    You can create your own User Defined Function to check for integers, like so:

    1. CREATE Function dbo.IsInteger(@Value VarChar(18))
    2. Returns Bit
    3. As
    4. Begin
    5.  
    6.   Return IsNull(
    7.      (Select Case When CharIndex('.', @Value) > 0
    8.                   Then Case When Convert(int, ParseName(@Value, 1)) <> 0
    9.                             Then 0
    10.                             Else 1
    11.                             End
    12.                   Else 1
    13.                   End
    14.       Where IsNumeric(@Value + 'e0') = 1), 0)
    15.  
    16. End

    To use this new function:

    1. Select Convert(int, field)
    2. From   Table
    3. Where  dbo.IsInteger(field) = 1

    If you want to allow fractional numbers, then you can add e0 to the isnumeric test.

    1. Select IsNumeric('$12.09' + 'e0')
    2. Select IsNumeric('1.4e3' + 'e0')
    3. Select IsNumeric('2d4' + 'e0')
    4. Select IsNumeric('3.7' + 'e0')

    Again, you can create a User Defined Function to test this.

    1. Create Function IsNumber(@Value VarChar(18))
    2. Returns Bit
    3. As
    4. Begin
    5.   Return (Select IsNumeric(@Value + 'e0'))
    6. End

    After creating the User Defined Functions, you can test it with the following code.

    1. Declare @Temp Table(Data VarChar(18))
    2.  
    3. Insert Into @Temp Values('$12.09')
    4. Insert Into @Temp Values('1.4e3')
    5. Insert Into @Temp Values('2d4')
    6. Insert Into @Temp Values('3.7')
    7. Insert Into @Temp Values('412')
    8.  
    9. Select Data,
    10.        IsNumeric(Data) As [IsNumeric],
    11.        dbo.IsInteger(Data) As IsInteger,
    12.        dbo.IsNumber(Data) As IsNumber
    13. From   @Temp

    About the Author

    George has been developing software professionally for 19 years, first for the department of defense, and then for various other companies. In 1998, George started his software company, Orbit Software, specializing in School Bus Transportation software. His specialty is refining SQL Server queries to deliver optimal performance.
    Social SitingsTwitterLTD RSS Feed
    InstapaperVote on HN

    8 comments

    Comment from: SQLDenis [Member] Email
    *****
    SQLDenis Very cool George, I am sure this will be very useful for a lot of our readers
    07/15/09 @ 08:23
    Comment from: Naomi Nosonovsky [Member]
    *****
    Naomi Nosonovsky Can you compare your approach with this
    http://berezniker.com/content/pages/sql/microsoft-sql-server/isnumericex-udf-data-type-aware
    07/15/09 @ 18:27
    Comment from: George Mastros (gmmastros) [Member]
    George Mastros (gmmastros) Naomi,

    The function at the link you posted could be pretty handy. My function executes faster (almost twice as fast), but the function you linked to has more features.

    It's the classic trade-off.
    07/15/09 @ 21:19
    Comment from: Joseph [Visitor]
    Joseph Is this post a copy of http://www.tek-tips.com/faqs.cfm?fid=6423 ?
    07/19/09 @ 02:41
    Comment from: Bruce W Cassidy [Visitor]
    ****-
    Bruce W Cassidy Since the number is already in a varchar, wouldn't it be quicker to use something like the following?

    if (@value like '%[^0-9]%) return 0 else return 1;
    07/19/09 @ 14:38
    Comment from: gunasundari [Visitor]
    *****
    gunasundari This is useful article..
    07/20/09 @ 00:18
    Comment from: SQLDenis [Member] Email
    *****
    SQLDenis Joseph,

    The author of this post and that FAQ is the same person
    07/20/09 @ 07:52
    Comment from: Grady Christie [Visitor] · http://www.centralfreight.com
    *****
    Grady Christie Thank you. I had been using isnumeric() for a while and someone entered only a decimal point causing some problems.
    This was a huge time saver for me; thanks for submitting.
    Grady Christie
    08/05/09 @ 12:32

    Leave a comment


    Your email address will not be revealed on this site.

    To mislead the spambots.

    Your URL will be displayed.
    (Line breaks become <br />)
    (Name, email & website)
    (Allow users to contact you through a message form (your email will not be revealed.)