0

最終的にdecimal(18,5)、int、またはタグ内にデータがない可能性のある一意の識別子として書き込まれるXmlドキュメントの着信値に対応するために何をする必要がありますか[ただし、NULLデータではありません--難しい方法を見つけたので]、またはタグ内のテキストデータ。1つの問題を解決したようですが、別の問題を作成します!:-\エラーが発生します:varchar値「7800.00000」をデータ型intに変換すると変換に失敗し、文字列からuniqueidentifierに変換すると変換に失敗しました。これを修正するにはどうすればよいですか?

データに含まれるxmlスニペットの例を次に示します。

<Products>
  <Product>
      <AgreementId>2439</AgreementId>
      <Difference>0.00400</Difference>
      <DispatchedQuantity>7800.00000</DispatchedQuantity>
      <Freight>0.01560</Freight>
      <ProductGUID>d475165c-0031-41f6-ad44-cecb73dfd2de</ProductGUID>
      <ShortName>U_B5Not Specif_No2_U</ShortName>
    </Product>
  </Products

ストアドプロシージャで処理するコードは次のとおりです。

 SELECT
       l.OrderId,
       l.OrderLiftId,
       cast(n.x.value('AgreementId[1]', 'varchar(20)') as int),
       CAST(CASE WHEN n.x.value('Difference[1]', 'varchar(20)') = '' THEN 0 ELSE  COALESCE(n.x.value('Difference[1]', 'varchar(20)'), '0.00') END AS decimal(18,5)),
       CAST(CASE WHEN n.x.value('DispatchedQuantity[1]', 'varchar(20)') = '' THEN 0 ELSE  COALESCE(n.x.value('DispatchedQuantity[1]', 'varchar(20)'), '0.00') END AS decimal(18,5)),
       CAST(CASE WHEN n.x.value('Freight[1]', 'varchar(20)') = '' THEN 0 ELSE  COALESCE(n.x.value('Freight[1]', 'varchar(20)'), '0.00') END AS decimal(18,5)),
       cast(n.x.value('ProductGUID[1]', 'varchar(40)') as uniqueidentifier),
       n.x.value('ShortName[1]', 'varchar(100)')
  FROM @lines as l
   CROSS APPLY l.lineprods.nodes('/Products/Product') as n(x);

更新:この行-

 CAST(CASE WHEN n.x.value('DispatchedQuantity[1]', 'varchar(20)') = '' THEN 0 ELSE  COALESCE(n.x.value('DispatchedQuantity[1]', 'varchar(20)'), '0.00') END AS decimal(18,5)),

次のように変更する必要があります:

 CAST(CASE WHEN n.x.value('DispatchedQuantity[1]', 'varchar(20)') = '' THEN 0 ELSE  COALESCE(n.x.value('DispatchedQuantity[1]', 'decimal(18,5)'), '0.00') END AS decimal(18,5)),

非数値/非ヌルおよび私が望む最初の非ヌルが小数であることに対応するために、他の趣味の値を取得した場合でも、爆発する可能性があります。それに対処する方法について何か提案はありますか?

4

2 に答える 2

1

これを試して。

declare @xml xml 

select @xml = '
<Products>
  <Product>
      <AgreementId>2439</AgreementId>
      <Difference>aaa</Difference>
      <DispatchedQuantity>7800.00000</DispatchedQuantity>
      <Freight>0.01560</Freight>
      <ProductGUID>d475165c-0031-41f6-ad44-cecb73dfd2de</ProductGUID>
      <ShortName>U_B5Not Specif_No2_U</ShortName>
    </Product>
  </Products>'

select
    CALC2.Agreement,
    CALC2.[Difference],
    CALC2.DispatchedQuantity,
    CALC2.ProductGUID,
    CALC2.Freight,
    CALC.ShortName
from @xml.nodes('/Products/Product') as n(x)
    outer apply
    (
        select
            isnull(n.x.value('AgreementId[1]', 'varchar(20)'), '0') as Agreement,
            isnull(n.x.value('Difference[1]', 'varchar(20)'), '0.00000') as     [Difference],
            isnull(n.x.value('DispatchedQuantity[1]', 'varchar(20)'), '0.00000') as DispatchedQuantity,
            n.x.value('ProductGUID[1]', 'varchar(40)') as ProductGUID,
            isnull(n.x.value('Freight[1]', 'varchar(20)'), '0.00000') as Freight,
            n.x.value('ShortName[1]', 'varchar(100)') as ShortName
    ) as CALC
    outer apply
    (
        select
            case when CALC.Agreement not like '%[^0-9]%' then cast(CALC.Agreement as int) else null end as Agreement,
            case when CALC.[Difference] not like '%[^0-9]%' then cast(CALC.[Difference] as decimal(18,5)) else null end as [Difference],
            case when CALC.DispatchedQuantity not like '%[^0-9]%' then null else cast(CALC.DispatchedQuantity as decimal(18,5)) end as DispatchedQuantity,
            cast(CALC.ProductGUID as uniqueidentifier) as ProductGUID,
            case when CALC.Freight not like '%[^0-9]%' then null else cast(CALC.Freight as decimal(18,5)) end as Freight
    ) as CALC2
于 2012-10-15T18:26:37.200 に答える
1

ISNUMERIC関数でうまくいくと思います。

CASE WHEN ISNUMERIC(n.x.value('DispatchedQuantity[1]', 'varchar(max)')) = 0 THEN 0 ELSE ... END

ただし、10進数にキャストする前にxmlをvarchar(20)として抽出している理由がわかりません。データが数値であることを確認したら、次のように簡単に使用できます。

n.x.value('DispatchedQuantity[1]', ' decimal(18,5)')

テストに使用した完全なSQL:

DECLARE @XML XML
SET @XML = '<Products>
              <Product>
                  <AgreementId>2439</AgreementId>
                  <Difference>0.00400</Difference>
                  <DispatchedQuantity>7800.00000</DispatchedQuantity>
                  <Freight>0.01560</Freight>
                  <ProductGUID>d475165c-0031-41f6-ad44-cecb73dfd2de</ProductGUID>
                  <ShortName>U_B5Not Specif_No2_U</ShortName>
                </Product>
                <Product>
                  <AgreementId>2439</AgreementId>
                  <Difference></Difference>
                  <DispatchedQuantity>INVALID NUMBER</DispatchedQuantity>
                  <Freight>INVALID FREIGHT</Freight>
                  <ProductGUID>INVALID GUID</ProductGUID>
                  <ShortName>U_B5Not Specif_No2_U</ShortName>
                </Product>
              </Products>'

SELECT  [AgreementId] = CAST(n.x.value('AgreementId[1]', 'varchar(20)') AS INT),
        [Difference] = CAST(CASE WHEN ISNUMERIC(n.x.value('Difference[1]', 'varchar(max)')) = 0 THEN 0 ELSE n.x.value('Difference[1]', 'decimal(18, 5)') END AS DECIMAL(18,5)),
        [DispatchedQuantity] = CAST(CASE WHEN ISNUMERIC(n.x.value('DispatchedQuantity[1]', 'varchar(max)')) = 0 THEN 0 ELSE n.x.value('DispatchedQuantity[1]', 'decimal(18, 5)') END AS DECIMAL(18,5)),
        [Freight] = CAST(CASE WHEN ISNUMERIC(n.x.value('Freight[1]', 'varchar(20)')) = 0 THEN 0 ELSE n.x.value('Freight[1]', ' decimal(18,5)') END AS DECIMAL(18,5)),
        [ProductGUID] = CASE WHEN ProductGUID LIKE Expression + '%' OR ProductGUID LIKE '{' + Expression + '}' THEN CAST(ProductGUID AS UNIQUEIDENTIFIER) END,
        [ShortName] = n.x.value('ShortName[1]', 'varchar(100)')
FROM    @XML.nodes('/Products/Product') AS n(x)
        CROSS APPLY 
        (   SELECT  [ProductGUID] = n.x.value('ProductGUID[1]', 'varchar(40)') ,
                    [Expression] = REPLACE('00000000-0000-0000-0000-000000000000', '0', '[0-9a-fA-F]') COLLATE Latin1_General_BIN 
        ) Expr 

編集

上記のクエリを編集して、無効なGUIDを許可しました( Martin Smithの助けを借りて)

SQL-Server 2012を使用している場合は、TRY_CONVERTを使用できます。

SELECT  [AgreementId] = TRY_CONVERT(INT, n.x.value('AgreementId[1]', 'varchar(20)')),
        [Difference] =TRY_CONVERT(DECIMAL(18, 5), n.x.value('Difference[1]', 'varchar(max)')),
        [DispatchedQuantity] = TRY_CONVERT(DECIMAL(18, 5), n.x.value('DispatchedQuantity[1]', 'varchar(max)')),
        [Freight] = TRY_CONVERT(DECIMAL(18, 5), n.x.value('Freight[1]', 'varchar(20)')),
        [ProductGUID] = TRY_CONVERT(UNIQUEIDENTIFIER, n.x.value('ProductGUID[1]', 'varchar(40)')),
        [ShortName] = n.x.value('ShortName[1]', 'varchar(100)')
FROM    @XML.nodes('/Products/Product') AS n(x)
于 2012-10-15T19:11:16.353 に答える