Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Применимо к:SQL Server
База данных
SQL AzureУправляемый экземпляр
SQL AzureБаза данных SQL в Microsoft Fabric
В этой статье описаны рекомендации по использованию методов типа данных 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
Замечание
Синтаксический анализ ошибок, вызванных средством синтаксического анализа XQuery (например, синтаксической ошибкой в XML- методе типа данных XML), прерывает активную транзакцию независимо от XACT_ABORT параметра текущего сеанса.
Одноэлементные проверки
Действия по расположению, параметры функции и операторы, требующие одноэлементных значений, возвращают ошибку, если компилятор не может определить, гарантируется ли одноэлемент во время выполнения. Эта проблема часто возникает при работе с нетипизированными данными. Например, при уточняющем запросе атрибута необходима информация о единственном родительском элементе. Указать порядковый номер, выбирающий единственный родительский узел, недостаточно. Вычисление сочетания 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-столбцу приводит к статической ошибке компиляции. Это связано с тем, что значение() ожидает однотонный узел в качестве первого аргумента, и компилятор не может определить, будет ли выполняться только один <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.