SQL XML .node .query () возвращает пустую строку вместо NULL, если узел таблицы существует - PullRequest
2 голосов
/ 29 июня 2019

Почему .query () возвращает пустую строку вместо NULL, если таблица не существует? Я новичок в запросах XML в SQL, так что я просто играю, и это было неожиданно.

Вот пример проблемы.

declare @xml xml

set @xml = N'<xdoc><Header><OrderID>1234</OrderID><Detail><ProductID>12345</ProductID><Amount>12.50</Amount></Detail></Header></xdoc>'

SELECT  
    Tbl.Col.value('OrderID[1]', 'varchar(10)') as OrderID,  
    Tbl.Col.query('Detail') as Detail
FROM @xml.nodes('//Header') Tbl(Col)

set @xml = N'<xdoc><Header><OrderID>1234</OrderID></Header></xdoc>'

SELECT  
    Tbl.Col.value('OrderID[1]', 'varchar(10)') as OrderID,  
    Tbl.Col.query('Detail') as Detail
FROM @xml.nodes('//Header') Tbl(Col)

Первый оператор выбора возвращается, как и ожидалось. Поле Detail представляет собой xml детали таблицы в заголовке.

Однако во втором операторе select в этой записи заголовка не было таблицы подробностей, поэтому я ожидал, что поле будет пустым вместо пустой строки.

выход

1 Ответ

0 голосов
/ 30 июня 2019

То, что вы хотите, возможно, но вы должны думать немного по-другому.В XML значение NULL обозначено отсутствующим узлом .

Кроме того, слово "значение" очень важно в этом предложении.Метод .value() вернет NULL, если искомого элемента нет..query() -метод в любом случае вернет фрагмент с типом XML.

XML состоит из узлов.Элементы (любые <SomeElement> вместе со всеми вложенными узлами) являются особым видом узла.Плавающий текст в элементе сам по себе является узлом.Посмотрите на эти примеры:

Ваш XML

declare @xml xml

set @xml = 
N'<xdoc>
  <Header>
    <OrderID>1234</OrderID>
    <Detail>
      <ProductID>12345</ProductID>
      <Amount>12.50</Amount>
    </Detail>
  </Header>
</xdoc>'

- .query() может вернуть <Detail> -фрагмент

SELECT @xml.query('/xdoc/Header/Detail');

<Detail>
  <ProductID>12345</ProductID>
  <Amount>12.50</Amount>
</Detail>

- Этот узел несуществовать.Вы получите не NULL -значение , а пустой XML-узел

SELECT @xml.query('/xdoc/Header/Dummy');                                       --<-- empty XML

- Теперь посмотрите на .value()

SELECT @xml.value('(/xdoc/Header/Dummy)[1]','nvarchar(100)');                  --<-- NULL
SELECT @xml.value('(/xdoc/Header/Detail)[1]','nvarchar(100)');                 --<-- 1234512.50
SELECT @xml.value('(/xdoc/Header/Detail/text())[1]','nvarchar(100)');          --<-- NULL
SELECT @xml.value('(/xdoc/Header/Detail/ProductID)[1]','nvarchar(100)');       --<-- 12345
SELECT @xml.value('(/xdoc/Header/Detail/ProductID/text())[1]','nvarchar(100)');--<-- 12345

Первый звонок ясен, <Dummy> нет, поэтому мы получаем NULL.
Второй звонок может вас удивить.Значение равно всему элементу .В этом случае мы получаем комбинацию всех значений.Возможно, вы рассматривали это как трюк для симуляции group_concat () .
Третий вызов возвращает NULL, поскольку в <Detail>
... и четвертом нет text()и пятый вызов возвращает то же самое, но последний с text() является наиболее конкретным и, следовательно, лучшим выбором.

Это зависит от ваших потребностей, что вы хотите запросить и что вы хотите получить обратно,Кроме того, вы можете использовать предикаты, такие как empty(SomeNode) или not(empty(SomeNode)), чтобы использовать фильтры XQuery в вашем XPath.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...