Xpathのみを使用してSQLサーバーの空のXMLタグからnullを返す方法は?


8

レコードに関するさまざまなユーザー定義データポイントをXML列に格納するアプリケーションがあります。これらがどのように保存または更新されるかは、私には制御できません。

列をクエリすると、3つの値のいずれかが返されます。

  1. ヌル
  2. 空の文字列

$ 64質問 xpathを使用して、空の文字列をnullとして返したいのですが。

nullを空の文字列として返すことに関する多くの答えを見つけましたが、この方法では何も起こりません。

それらは、誰かが値を削除したときにそのようになり、タグを削除するのではなく、タグにブランクになり<value />ます。nullは、値が設定されていない場合に発生します。xsi:nilは含まれていません。

私はケースステートメントでそれをしました:

    select
    so.SalesOrderId,
    Case
        when sopc.value('(Value)[1]','smalldatetime') IS null then Null
        when sopc.value('(Value)[1]','smalldatetime') ='' then Null
        Else sopc.value('(Value)[1]','smalldatetime')
    End as sopc
    From
    SalesOrders so
    Outer apply so.CustomColumns.nodes('/CustomColumnsCollection/CustomColumn[Name="ProjCompleted"]') sopc(sopc)

しかし、これは非効率に感じられ、これが唯一の列ではないため、コードが長くなり、保守が難しくなります。

編集してサンプルデータを含めます

SalesOrderId    CustomColumns
SO 1            "<CustomColumnsCollection>
                   <CustomColumn>
                     <Name>ProjCompleted</Name>
                     <DataType>1</DataType>
                     <Value />
                   </CustomColumn>
                 </CustomColumnsCollection>"
SO 2           "<CustomColumnsCollection>
                  <CustomColumn>
                     <Name>ProjCompleted</Name>
                     <DataType>1</DataType>
                     <Value>'2017-11-21'</Value>
                  </CustomColumn>
                </CustomColumnsCollection>"
SO 3           "<CustomColumnsCollection>
                </CustomColumnsCollection>"

**Output**
Current      Desired
''           null
2017-11-21   2017-11-21
null         null

前もって感謝します。


ありがとうスコット-あなたが見ることができるように、それは私の最初の質問です、好ましい形式はありますか?
TimNewman 2017年

XMLサンプルが含まれているコードブロック(既に投稿したコードと同様)で質問を更新し、期待される結果の別のコードブロックを含めるだけです。最小限の完全な検証可能な例を作成する方法を
Scott Hodgin 2017年

ありがとう-回答を受け入れましたが、これを見つけた他の人に役立つように質問を編集します。
TimNewman 2017年

回答:


11

要素text()内のノードを指定しますValue。空のタグがある場合、そのノードはありません。

これを試して:

declare @X xml;
set @X = '<Value/>';

select @X.value('(Value/text())[1]', 'smalldatetime'),
       @X.value('(Value/text())[1]', 'varchar(max)'),
       @X.value('(Value/text())[1]', 'int'),
       @X.value('(Value)[1]', 'smalldatetime'),
       @X.value('(Value)[1]', 'varchar(max)'),
       @X.value('(Value)[1]', 'int');

結果:

------------------- ---------- ----------- ----------------------- ---------- -----------
NULL                NULL       NULL        1900-01-01 00:00:00                0

一般に、常にtext()ノードを指定することをお勧めします。クエリプランはよりシンプルで効率的です。

ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.