#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()
здесь, заключается в том, что мне нужно будет присоединить другую таблицу к функции thelocal-name(.)
и theatt.value(N'(.text())[1]', 'nvarchar(50)')
. Приведенный выше запрос дает мне одну строку со всеми дочерними элементами и значениями; мне нужен каждый в отдельной строке, чтобы я мог сравнивать значения по отдельности (мои ожидаемые значения приведены в моем последнемcode
блоке выше)2. @JonAgnich, спасибо за разъяснения. Хотя (1) с вашей стороны все еще отсутствует. Нам нужно полное воспроизведение.
3. @JonAgnich, пожалуйста, свяжитесь со мной в LinkedIn.