web-dev-qa-db-fra.com

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

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 retourner ces chaînes vides en tant que 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 <value /> tag. 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.

8
TimNewman

Spécifiez le nœud text() dans l'élément Value. 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 noeud text(). Le plan de requête est plus simple et plus efficace.

enter image description here

11
Mikael Eriksson