SQL Server 2014: функция apply against xml nodes () внезапно перестает работать

#sql-server #xml

#sql-сервер #xml

Вопрос:

У меня есть хранимая процедура, которая внезапно начала возвращать значение NULL только на одной из двух предположительно эквивалентных машин SQL Server 2014 (основной и аварийно-восстановительной).

Конкретная операция, которая внезапно ведет себя неправильно, это:

     declare @skus TABLE (intSkuId int, attributes xml);
    insert into @skus
    VALUES
        (11443, '<attributes><style>basic_mug</style><color>white</color><size>15oz</size></attributes>'),
        (11444, '<attributes><style>basic_mug</style><color>black</color><size>15oz</size></attributes>');

    select 
        s.intSkuId, s.xmlAttributes,  
        att.query('.') as element 
    from 
        tb_Skus s
    outer apply 
        xmlAttributes.nodes(N'//attributes/*') as atts(att)
    where 
        s.intSkuId = 11443;
  

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

Это возвращает следующий результат:

 intSkuId: 11443
xmlAttributes: <attributes><style>basic_mug</style><color>white</color><size>15oz</size></attributes>
element: NULL
  

Также обратите внимание, что следующий скрипт работает так, как задумано:

 DECLARE @x xml;

SELECT @x = xmlAttributes 
FROM tb_Skus s 
WHERE s.intSkuId = 11443

SELECT @x AS xmlAttributes, att.query('.') AS element
FROM @x.nodes(N'//attributes/*') AS atts(att)
  

выдает то же значение для XmlAttribute, но я получаю ожидаемые значения для элемента:

 <style>basic_mug</style>
<color>white</color>
<size>15oz</size>
  

Итак, что-то не так с первым запросом? И если нет, существуют ли настройки сеанса или базы данных, которые могут изменить поведение этой функции?

Комментарии:

1. Задавая вопрос, вам необходимо предоставить минимальный воспроизводимый пример: (1) Заполнение DDL и выборки данных, т.е. Создать таблицу (таблицы) плюс инструкции INSERT, T-SQL. (2) Что вам нужно сделать, т.Е. логика, и ваша попытка реализовать ее в T-SQL. (3) Желаемый результат на основе образца данных в # 1 выше. (4) Ваша версия SQL Server (ВЫБЕРИТЕ @@version;)

2. … двоичные значения должны быть одинаковыми: select attributes.value('local-name(/*[1])', 'nvarchar(max)'), cast(attributes.value('local-name(/*[1])', 'nvarchar(max)') as varbinary(100)) as xmlbinary, cast(N'attributes' as varbinary(100)) strbinary from tb_Skus where intSkuId = 11443

Ответ №1:

В этом случае нет необходимости использовать .nodes() метод. Это необходимо только тогда, когда необходимо преобразовать / измельчить тип данных XML в прямоугольные / реляционные данные.

Пожалуйста, попробуйте следующее.

SQL

 -- DDL and sample data population, start
DECLARE @tbl TABLE (intSkuId INT, xmlAttributes XML);
INSERT INTO @tbl (intSkuId, xmlAttributes) VALUES
(11443,  N'<attributes>
    <style>basic_mug</style>
    <color>white</color>
    <size>15oz</size>
</attributes>');
-- DDL and sample data population, end

SELECT *
    , xmlAttributes.query('/attributes/*') AS [element]
FROM @tbl
where intSkuId=11443;
  

Комментарии:

1. Я максимально упростил запрос, но причина, по которой я использую .nodes() здесь, заключается в том, что мне нужно будет присоединить другую таблицу к функции the local-name(.) и the att.value(N'(.text())[1]', 'nvarchar(50)') . Приведенный выше запрос дает мне одну строку со всеми дочерними элементами и значениями; мне нужен каждый в отдельной строке, чтобы я мог сравнивать значения по отдельности (мои ожидаемые значения приведены в моем последнем code блоке выше)

2. @JonAgnich, спасибо за разъяснения. Хотя (1) с вашей стороны все еще отсутствует. Нам нужно полное воспроизведение.

3. @JonAgnich, пожалуйста, свяжитесь со мной в LinkedIn.