Метод value() (тип данных xml)
Выполняет запрос XQuery к структуре XML и возвращает значение типа SQL. Данный метод возвращает скалярное значение.
Обычно этот метод применяется для извлечения значения из экземпляра XML, который хранится в столбце, параметре или переменной типа xml. При этом его можно использовать в запросах SELECT для объединения или сравнения данных XML с данными в столбцах других типов.
Применимо для следующих объектов: SQL Server (SQL Server 2008 по текущую версию), База данных SQL Windows Azure (С первоначального выпуска по текущий выпуск). |
Синтаксис
value (XQuery, SQLType)
Аргументы
XQuery
Выражение XQuery — строковый литерал, извлекающий данные из экземпляра XML. Выражение XQuery должно возвращать не более одного значения. В противном случае произойдет ошибка.SQLType
Предпочтительный тип SQL — строковый литерал, который необходимо вернуть. Тип возвращаемого этим методом значения соответствует значению параметра SQLType. Значением параметра SQLType не может быть тип данных xml, определяемый пользователем тип CLR, image, text, ntext, а также тип данных sql_variant. Значением параметра SQLType может быть SQL и определяемый пользователем тип данных.
Метод value() неявно использует оператор языка Transact-SQL CONVERT и пытается преобразовать результат выражения XQuery, сериализованное строковое представление, из типа данных XSD в соответствующий тип SQL, указанный преобразованием языка Transact-SQL. Дополнительные сведения о правилах приведения типов для оператора CONVERT см. Функции CAST и CONVERT (Transact-SQL).
Примечание
Для увеличения производительности операции сравнения с реляционным значением вместо метода value() в предикате используйте метод exist() совместно с sql:column().Это показано в следующем примере Г.
Примеры
А.Использование метода value() над переменной типа xml
В следующем примере экземпляр XML хранится в переменной типа xml. Метод value() извлекает из переменной XML значение атрибута ProductID. Затем полученное значение присваивается переменной типа int.
DECLARE @myDoc xml
DECLARE @ProdID int
SET @myDoc = '<Root>
<ProductDescription ProductID="1" ProductName="Road Bike">
<Features>
<Warranty>1 year parts and labor</Warranty>
<Maintenance>3 year parts and labor extended maintenance is available</Maintenance>
</Features>
</ProductDescription>
</Root>'
SET @ProdID = @myDoc.value('(/Root/ProductDescription/@ProductID)[1]', 'int' )
SELECT @ProdID
В результате возвращается значение 1.
Хотя экземпляр XML содержит только один атрибут ProductID, правила статической типизации требуют явно указать, что выражение пути возвращает единственное значение. Поэтому в конце выражения пути указан дополнительный знак [1]. Дополнительные сведения о статической типизации см. XQuery и статическая типизация.
Б.Использование метода value() для извлечения значения из столбца типа xml
В следующем примере выполняется запрос к столбцу типа xml (CatalogDescription) в базе данных AdventureWorks. Запрос извлекает значения атрибутов ProductModelID из каждого экземпляра XML, который хранится в столбце.
SELECT CatalogDescription.value('
declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
(/PD:ProductDescription/@ProductModelID)[1]', 'int') AS Result
FROM Production.ProductModel
WHERE CatalogDescription IS NOT NULL
ORDER BY Result desc
В приведенном запросе обратите внимание на следующие моменты.
Для определения префикса пространства имен используется ключевое слово namespace.
Требования к статической типизации в выражении пути обязывают в методе value() добавлять [1] в конце выражения пути, чтобы явно указать, что оно возвращает единственное значение.
Частичный результат:
-----------
35
34
...
В.Использование методов value() и exist() для извлечения значений из столбца типа xml
В следующем примере демонстрируется совместное использование методов value() и exist(), возвращающих тип данных xml. Метод value() извлекает значения атрибутов ProductModelID из экземпляров XML. Метод exist() в предложении WHERE фильтрует строки, извлеченные из таблицы.
Запрос извлекает идентификаторы моделей продуктов из экземпляров XML, которые среди прочих данных содержат сведения о гарантии (элемент <Warranty>). Условие в предложении WHERE приводит к тому, что метод exist() извлекает только те строки, которые соответствуют условию.
SELECT CatalogDescription.value('
declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
(/PD:ProductDescription/@ProductModelID)[1] ', 'int') as Result
FROM Production.ProductModel
WHERE CatalogDescription.exist('
declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
declare namespace wm="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain";
/PD:ProductDescription/PD:Features/wm:Warranty ') = 1
В предыдущем запросе обратите внимание на следующее.
Столбец CatalogDescription является типизированным XML-столбцом. Это означает, что с ним связан набор схем. В XQuery Prolog объявлено пространство имен, определяющее префикс, который затем используется в теле запроса.
Если метод exist() возвращает значение 1 (TRUE), это значит, что экземпляр XML содержит дочерний элемент <Warranty>.
Метод value() в предложении SELECT затем извлекает значения атрибутов ProductModelID в виде целых чисел.
Частичный результат:
Result
-----------
19
23
...
Г.Использование метода exist() вместо метода value()
Для увеличения производительности операции сравнения с реляционным значением вместо метода value() в предикате используйте метод exist() совместно с sql:column(). Например:
CREATE TABLE T (c1 int, c2 varchar(10), c3 xml)
GO
SELECT c1, c2, c3
FROM T
WHERE c3.value( '/root[1]/@a', 'integer') = c1
GO
Запрос будет выглядеть следующим образом:
SELECT c1, c2, c3
FROM T
WHERE c3.exist( '/root[@a=sql:column("c1")]') = 1
GO
См. также
Основные понятия
Добавление пространств имен в запросы с WITH XMLNAMESPACES
Сравнение типизированного и нетипизированного XML
Создание экземпляров XML-данных
Язык модификации XML-данных (XML DML)