SQL IsNumeric not working

前端 未结 11 859
迷失自我
迷失自我 2021-01-02 19:47

The reserve column is a varchar, to perform sums on it I want to cast it to a deciaml. But the SQL below gives me an error

select
cast(Reserve as decimal)
fr         


        
11条回答
  •  刺人心
    刺人心 (楼主)
    2021-01-02 20:08

    IsNumeric is a problem child -- SQL 2012 and later has TRY_CAST and TRY_CONVERT

    If you're on an earlier version then you can write a function that'll convert to a decimal (or NULL if it won't convert). This uses the XML conversion functions that don't throw errors when the number won't fit ;)

    -- Create function to convert a varchar to a decimal (returns null if it fails)
    IF EXISTS( SELECT * FROM sys.objects WHERE object_id = OBJECT_ID( N'[dbo].[ToDecimal]' ) AND type IN( N'FN',N'IF',N'TF',N'FS',N'FT' ))
        DROP FUNCTION [dbo].[ToDecimal];
    GO
    
    CREATE FUNCTION ToDecimal
    (   
        @Value VARCHAR(MAX)
    )
    RETURNS DECIMAL(18,8)
    AS
    BEGIN
        -- Uses XML/XPath to convert @Value to Decimal because it returns NULL it doesn't cast correctly
        DECLARE @ValueAsXml XML
        SELECT @ValueAsXml = Col FROM (SELECT (SELECT @Value as Value FOR XMl RAW, ELEMENTS) AS Col) AS test
        DECLARE @Result DECIMAL(38,10)
        -- XML/XPath will return NULL if the VARCHAR can't be converted to a DECIMAL(38,10)
        SET @Result =  @ValueAsXml.value('(/row/Value)[1] cast as xs:decimal?', 'DECIMAL(38,10)')
        RETURN CASE -- Check if the number is within the range for a DECIMAL(18,8)
            WHEN @Result >= -999999999999999999.99999999 AND @Result <= 999999999999999999.99999999
                THEN CONVERT(DECIMAL(18,8),@Result) 
            ELSE 
                NULL
        END
    END
    

    Then just change your query to:

    select dbo.ToDecimal(Reserve) from MyReserves
    

提交回复
热议问题