How can I query 'between' numeric data on a not numeric field?

后端 未结 4 466
别那么骄傲
别那么骄傲 2021-01-18 04:25

I\'ve got a query that I\'ve just found in the database that is failing causing a report to fall over. The basic gist of the query:

Select *
From table
Wher         


        
相关标签:
4条回答
  • 2021-01-18 04:33

    Use a CASE statement.

    declare @StartRange int
    declare @EndRange int
    
    set @StartRange = 1
    set @EndRange = 3
    
    select *
    from TestData
    WHERE Case WHEN ISNUMERIC(Value) = 0 THEN 0
                WHEN Value IS NULL THEN 0
                WHEN Value = '' THEN 0
                WHEN CONVERT(int, Value) BETWEEN @StartRange AND @EndRange THEN 1
                END = 1
    
    0 讨论(0)
  • 2021-01-18 04:40

    Not sure if this helps you, but I did read somewhere that incorrect conversion using CONVERT will always generate error in SQL. So I think it would be better to use CASE in where clause to avoid having CONVERT to run on all rows

    0 讨论(0)
  • 2021-01-18 04:51

    IsNumeric only tells you that the string can be converted to one of the numeric types in SQL Server. It may be able to convert it to money, or to a float, but may not be able to convert it to an int.

    Change your

    IsNumeric(myField) = 1
    

    to be:

    not myField like '%[^0-9]%' and LEN(myField) < 9
    

    (that is, you want myField to contain only digits, and fit in an int)

    Edit examples:

    select ISNUMERIC('.'),ISNUMERIC('£'),ISNUMERIC('1d9')
    

    result:

    ----------- ----------- -----------
    1           1           1
    
    (1 row(s) affected)
    
    0 讨论(0)
  • 2021-01-18 04:53

    You'd have to force SQL to evaluate the expressions in a certain order. Here is one solution

    Select *
    From ( TOP 2000000000
       Select *
       From table
       Where IsNumeric(myField) = 1
       And IsNull(myField, '') <> ''
       ORDER BY Key
    ) t0
    Where Convert(int, myField) Between @StartRange And @EndRange
    

    and another

    Select *
    From table
    Where
    
    CASE
       WHEN IsNumeric(myField) = 1 And IsNull(myField, '') <> ''
       THEN Convert(int, myField) ELSE @StartRange-1
    END Between @StartRange And @EndRange
    
    • The first technique is "intermediate materialisation": it forces a sort on a working table.
    • The 2nd relies on CASE ORDER evaluation is guaranteed
    • Neither is pretty or whizzy

    SQL is declarative: you tell the optimiser what you want, not how to do it. The tricks above force things to be done in a certain order.

    0 讨论(0)
提交回复
热议问题