Правила использования методов типа данных XML
Область применения: SQL Server База данных SQL Azure Управляемый экземпляр SQL Azure
В этом разделе описываются правила использования методов типа данных xml.
Инструкция PRINT
Методы типа данных xml не могут быть использованы в инструкции PRINT, как показано в следующем примере. Методы типа данных xml обрабатываются как подзапросы, а подзапросы в инструкции PRINT не разрешены. В результате следующий пример возвращает ошибку:
DECLARE @x XML
SET @x = '<root>Hello</root>'
PRINT @x.value('/root[1]', 'varchar(20)') -- will not work because this is treated as a subquery (select top 1 col from table)
В качестве решения можно вначале присвоить результат метода value() переменной типа xml, а потом использовать переменную в запросе.
DECLARE @x XML
DECLARE @c VARCHAR(max)
SET @x = '<root>Hello</root>'
SET @c = @x.value('/root[1]', 'VARCHAR(11)')
PRINT @c
Предложение GROUP BY
Методы типа данных xml интерпретируются внутри как подзапросы. Так как предложение GROUP BY требует скалярного выражения и не принимает статистических вычислений или подзапросов, нельзя указывать методы типа данных xml в предложении GROUP BY. Решением является вызов пользовательской функции, которая использует методы XML.
Ведение отчетов об ошибках
При сообщении об ошибках методы типа данных xml вызывают ошибки в следующем формате:
Msg errorNumber, Level levelNumber, State stateNumber:
XQuery [database.table.method]: description_of_error
Например:
Msg 2396, Level 16, State 1:
XQuery [xmldb_test.xmlcol.query()]: Attribute may not appear outside of an element
Одноэлементные проверки
Шаги определения расположения данных, параметры функций и операторы, которым нужны единственные значения, возвращают ошибку, если компилятор не может определить, будет ли в период выполнения гарантирована единственность элемента. Эта проблема часто возникает при работе с нетипизированными данными. Например, при уточняющем запросе атрибута необходима информация о единственном родительском элементе. Указать порядковый номер, выбирающий единственный родительский узел, недостаточно. Чтобы извлечь значения атрибутов при обработке комбинации node()-value(), указание порядкового номера, возможно, не потребуется. Это показано в следующем примере.
Пример. Известный единственный экземпляр
В этом примере метод nodes() создает отдельную строку для каждого элемента <book>
. Метод value(), выполняемый для узла <book>
, извлекает значение @genre
, которое, будучи атрибутом, является единственным.
SELECT nref.value('@genre', 'VARCHAR(max)') LastName
FROM T CROSS APPLY xCol.nodes('//book') AS R(nref)
Чтобы проверить типы типизированного XML, используется XML-схема. Если в XML-схеме узел указан как единственный, компилятор это учитывает, и ошибки не возникают. В противном случае необходим порядковый номер, выбирающий единственный узел. В частности, использование оси ось нисходящих или самозадавленных (/) ( например /book//title
, теряет вывод одноэлементной кратности для <title>
элемента, даже если схема XML указывает, что это так. Поэтому следует переписать его как (/book//title)[1]
.
Важно знать о различии между выражениями //first-name[1]
и (//first-name)[1]
при проверке типов. Первое из них возвращает последовательность узлов <first-name>
, в которой каждый узел является самым левым узлом <first-name>
среди узлов с общим родителем. Второе возвращает первый единственный узел <first-name>
в порядке документа в экземпляре XML.
Пример. Использование value()
Следующий запрос данных из нетипизированного столбца XML приводит к статической ошибке компиляции. Это объясняется тем, что метод value() ожидает в качестве первого аргумента единственный узел, а компилятор не может определить, будет ли в период выполнения существовать только один узел <last-name>
:
SELECT xCol.value('//author/last-name', 'NVARCHAR(50)') LastName
FROM T
Вот решение этой проблемы, которое возможно как вариант:
SELECT xCol.value('//author/last-name[1]', 'NVARCHAR(50)') LastName
FROM T
Однако это решение не устраняет ошибку, потому что в каждом экземпляре XML могут содержаться несколько узлов <author>
. Следующий вариант работает:
SELECT xCol.value('(//author/last-name/text())[1]', 'NVARCHAR(50)') LastName
FROM T
Этот запрос возвращает значение первого элемента <last-name>
в каждом из экземпляров XML.
См. также
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по