【问题标题】:MsSQL xml parse to decimalMsSQL xml 解析为十进制
【发布时间】:2023-04-03 13:05:01
【问题描述】:

我正在用这个存储过程处理 xml

select
    col.query('./AgreementId').value('.','uniqueidentifier') as [AgreementId],
    x.query('./GrossValue').value('.','decimal(19, 4)') as [GrossValue]
    into #AdvanceInvoices
    from @XML.nodes('/DataFromERP/CustomObjects/Agreements/Agreement') as ref(col)
    cross apply ref.col.nodes('AdvanceInvoices/AdvanceInvoice') as T(x)

问题是GrossValue,可以为空

<GrossValue></GrossValue>

而且可能会出现错误

Error converting data type nvarchar to numeric

我怎样才能让它得到 0.0 而不是错误?

编辑:

我想出了

CAST(COALESCE(NULLIF(ISNULL(x.query('./GrossValue').value('.','nvarchar(50)'),''),''),'0.0') as decimal(19,4)) as [GrossValue],

但是真的很丑

【问题讨论】:

    标签: sql-server xml tsql null type-conversion


    【解决方案1】:

    您可以尝试从元素中获取 VARCHAR 值,使用TRY_CAST 转换为十进制,如果值为 NULL,则使用 ISNULL 获取 0.0。

    ISNULL(TRY_CAST(x.query('./GrossValue').value('.','VARCHAR(20)') AS DECIMAL(19,4)),.0) AS [GrossValue]
    

    和我想的一样丑。

    【讨论】:

    • 这可行,但仅限于 SQL Server 2012+(我的支持)
    【解决方案2】:

    早在TRY_CASTTRY_CONVERT 被发明之前,就有XQuery 演员表:

    DECLARE @SomeTable TABLE(ID INT IDENTITY, SomeXML XML);
    INSERT INTO @SomeTable VALUES
     (N'<DATA><SomeNumber>1</SomeNumber></DATA>')     --integer
    ,(N'<DATA><SomeNumber>1.1</SomeNumber></DATA>')   --decimal
    ,(N'<DATA><SomeNumber></SomeNumber></DATA>')      --empty
    ,(N'<DATA><SomeNumber>abc</SomeNumber></DATA>')   --invalid
    ,(N'<DATA><SomeNumber>.123</SomeNumber></DATA>')  --short
    
    SELECT t.SomeXML.value(N'/DATA[1]/SomeNumber[1]/text()[1] cast as xs:decimal?',N'decimal(19,4)')
    FROM @SomeTable AS t
    

    当值不可转换时,使用cast as xs:decimal? 将返回NULL

    为了获得0.0 而不是NULL,您可以使用ISNULL()-函数(正如TT 所指出的那样)。

    作为提示:

    在旧版本中,如果 TRY_ 调用不起作用,这是一个很好的解决方法:

    DECLARE @InvalidNumber VARCHAR(100)='123a'
           ,@ValidNumber VARCHAR(100)='123';
    
    SELECT (SELECT @InvalidNumber FOR XML PATH(''),TYPE).value(N'. cast as xs:int?',N'int') AS InvalidNumber
          ,(SELECT @ValidNumber FOR XML PATH(''),TYPE).value(N'. cast as xs:int?',N'int') AS ValidNumber;
    

    或者更简单,只是一个演员表:

    DECLARE @InvalidNumber VARCHAR(100)='123a'
           ,@ValidNumber VARCHAR(100)='123';
    
    SELECT CAST(@InvalidNumber AS XML).value(N'. cast as xs:int?',N'int') AS InvalidNumber
          ,CAST(@ValidNumber AS XML).value(N'. cast as xs:int?',N'int') AS ValidNumber
    

    【讨论】:

    • 我们不得不等待您提出基于 XQuery 的更好解决方案 :) +1
    猜你喜欢
    • 1970-01-01
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    • 2018-12-26
    • 2010-12-30
    • 1970-01-01
    相关资源
    最近更新 更多