Wie kann eine Null von einem leeren XML-Tag in SQL Server nur mit Xpath zurückgegeben werden?

8

Ich habe eine Anwendung, die verschiedene benutzerdefinierte Datenpunkte zu einem Datensatz in einer XML-Spalte speichert. Ich habe keine Kontrolle darüber, wie diese gespeichert oder aktualisiert werden.

Wenn ich eine Spalte abfrage, kann sie 1 von 3 Werten zurückgeben:

  1. Der Wert
  2. Null
  3. Eine leere Zeichenfolge

$ 64 Frage Ich möchte diese leeren Zeichenfolgen mit xpath als Nullen zurückgeben.

Ich habe viele Antworten gefunden, um die Null als leeren Stich zurückzugeben, aber nichts in dieser Richtung.

Sie enden auf diese Weise, wenn jemand den Wert gelöscht hat, und anstatt das Tag zu löschen, wird es zu einem <value />Tag ausgeblendet. Die Nullen treten auf, wenn der Wert nie festgelegt wurde. Sie haben xsi: nil nicht enthalten.

Ich habe es mit einer Fallaussage gemacht:

    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)

Dies fühlt sich jedoch ineffizient an und ist nicht die einzige Spalte, sodass der Code lang und schwieriger zu warten ist.

Bearbeiten, um Beispieldaten einzuschließen

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

Danke im Voraus.

TimNewman
quelle
Danke Scott - wie Sie sehen, ist es meine erste Frage, gibt es ein bevorzugtes Format?
TimNewman
Aktualisieren Sie Ihre Frage einfach mit einem Codeblock (ähnlich dem bereits veröffentlichten Code), der das XML-Beispiel enthält, und fügen Sie einen weiteren Codeblock mit den erwarteten Ergebnissen hinzu. Siehe So erstellen Sie ein minimales, vollständiges und überprüfbares Beispiel
Scott Hodgin
Danke - Ich habe eine Antwort akzeptiert, aber ich werde die Frage trotzdem bearbeiten, um sie für alle anderen nützlich zu machen, die dies finden.
TimNewman

Antworten:

11

Geben Sie den text()Knoten innerhalb des ValueElements an. Dieser Knoten fehlt, wenn Sie ein leeres Tag haben.

Versuche dies:

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');

Ergebnis:

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

Im Allgemeinen ist es gut, immer den text()Knoten anzugeben . Der Abfrageplan ist einfacher und effizienter.

Geben Sie hier die Bildbeschreibung ein

Mikael Eriksson
quelle