Comment retourner un null à partir d'une balise XML vide dans SQL Server en utilisant uniquement Xpath?

8

J'ai une application qui stocke divers points de données définis par l'utilisateur sur un enregistrement dans une colonne XML. Je n'ai aucun contrôle sur la façon dont ceux-ci sont stockés ou mis à jour.

Lorsque je recherche une colonne, elle peut renvoyer 1 valeur sur 3:

  1. La valeur
  2. Nul
  3. Une chaîne vide

$ 64 question Je voudrais renvoyer ces chaînes vides sous forme de null en utilisant xpath.

J'ai trouvé beaucoup de réponses sur le retour du null comme une piqûre vide mais rien de cette façon.

Ils finissent de cette façon lorsque quelqu'un a supprimé la valeur et au lieu de supprimer la balise, il la vide en une <value />balise. Les valeurs NULL se produisent lorsque la valeur n'a jamais été définie. Ils n'ont pas inclus xsi: nil.

Je l'ai fait avec une déclaration de cas:

    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)

mais cela semble inefficace et ce n'est pas la seule colonne donc cela rend le code long et plus difficile à maintenir.

Modifier pour inclure des exemples de données

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

Merci d'avance.

TimNewman
la source
Merci Scott - comme vous pouvez le voir, c'est ma première question, y a-t-il un format préféré?
TimNewman
Mettez simplement à jour votre question avec un bloc de code (similaire au code que vous avez déjà publié) qui a l'exemple XML et incluez un autre bloc de code des résultats attendus. Voir Comment créer un exemple minimal, complet et vérifiable
Scott Hodgin
Merci - J'ai accepté une réponse, mais je vais quand même modifier la question pour la rendre utile à quiconque la trouvera.
TimNewman

Réponses:

11

Spécifiez le text()nœud dans l' Valueélément. Ce nœud est manquant lorsque vous avez une balise vide.

Essaye ça:

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

Résultat:

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

C'est une bonne chose en général de toujours spécifier le text()nœud. Le plan de requête est plus simple et plus efficace.

entrez la description de l'image ici

Mikael Eriksson
la source