Как вернуть ноль из пустого тега XML на сервере SQL, используя только Xpath?

8

У меня есть приложение, которое хранит различные пользовательские точки данных о записи в столбце XML. Я не контролирую, как они хранятся или обновляются.

Когда я запрашиваю столбец, он может вернуть 1 из 3 значений:

  1. Значение
  2. Значение NULL
  3. Пустая строка

$ 64 вопрос Я хотел бы вернуть эти пустые строки как нули, используя xpath.

Я нашел много ответов о возврате нулевого значения в виде пустого укуса, но ничего такого не получилось.

Они заканчивают тем же способом, когда кто-то удаляет значение, и вместо удаления тега он очищает его от <value />тега. Нули появляются, когда значение никогда не было установлено. Они не включили xsi: nil.

Я сделал это с помощью case case:

    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
источник
Спасибо Скотт - как вы видите, это мой первый вопрос, есть ли предпочтительный формат?
TimNewman
Просто обновите свой вопрос с помощью блока кода (похожего на код, который вы уже опубликовали), который содержит образец XML и включает другой блок кода с ожидаемыми результатами. См. Раздел « Как создать минимальный, полный и проверяемый пример»
Скотт Ходжин,
Спасибо - я принял ответ, но я все равно отредактирую вопрос, чтобы сделать его полезным для всех, кто найдет это.
TimNewman

Ответы:

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()узел. План запросов проще и эффективнее.

введите описание изображения здесь

Микаэль Эрикссон
источник