¿Cómo devolver un valor nulo de una etiqueta XML vacía en el servidor SQL usando Xpath solamente?

8

Tengo una aplicación que almacena varios puntos de datos definidos por el usuario sobre un registro en una columna XML. No tengo control sobre cómo se almacenan o actualizan.

Cuando consulto una columna, puede devolver 1 de 3 valores:

  1. El valor
  2. Nulo
  3. Una cadena vacía

Pregunta de $ 64 Me gustaría devolver esas cadenas vacías como nulas usando xpath.

He encontrado muchas respuestas sobre devolver el nulo como una picadura vacía, pero nada de esta manera.

Terminan de esa manera cuando alguien ha eliminado el valor y, en lugar de eliminar la etiqueta, la pone en blanco en una <value />etiqueta. Los valores nulos se producen cuando el valor nunca se ha establecido. No han incluido xsi: nil.

Lo hice con una declaración de caso:

    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)

pero esto se siente ineficiente y esta no es la única columna, por lo que hace que el código sea largo y difícil de mantener.

Editar para incluir datos de muestra

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

Gracias por adelantado.

TimNewman
fuente
Gracias Scott, como puedes ver es mi primera pregunta, ¿hay un formato preferido?
TimNewman
Simplemente actualice su pregunta con un bloque de código (similar al código que ya ha publicado) que tiene la muestra XML e incluya otro bloque de código de los resultados esperados. Vea cómo crear un ejemplo mínimo, completo y verificable
Scott Hodgin el
Gracias. He aceptado una respuesta, pero aún así editaré la pregunta para que sea útil para cualquier otra persona que la encuentre.
TimNewman

Respuestas:

11

Especifique el text()nodo dentro del Valueelemento. Ese nodo falta cuando tiene una etiqueta vacía.

Prueba esto:

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

Resultado:

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

En general, es bueno especificar siempre el text()nodo. El plan de consulta es más simple y más eficiente.

ingrese la descripción de la imagen aquí

Mikael Eriksson
fuente