value() 方法(xml 数据类型)

对 XML 执行 XQuery,并返回 SQL 类型的值。此方法将返回标量值。

通常,可以使用此方法从 xml 类型列、参数或变量内存储的 XML 实例中提取值。这样,您就可以指定将 XML 数据与非 XML 列中的数据进行合并或比较的 SELECT 查询。

语法

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 类型转换为由 Transact-SQL 转换指定的相应 SQL 类型。有关 CONVERT 的类型转换规则的详细信息,请参阅 CAST 和 CONVERT (Transact-SQL)

注意注意

由于性能原因,不在谓词中使用 value() 方法与关系值进行比较,而改用具有 sql:column()exist()。如下面的示例 D 所示。

示例

A. 对 xml 类型的变量使用 value() 方法

在下面的示例中,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。因此,在路径表达式结尾处指定了另一个 [1]。有关静态类型化的详细信息,请参阅 XQuery 与静态类型化

B. 使用 value() 方法从 xml 类型的列中检索值

以下查询根据 AdventureWorks2008R2 数据库中的 xml 类型列 (CatalogDescription) 指定。查询从列中存储的每个 XML 实例中检索 ProductModelID 属性值。

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] 以显式指示路径表达式返回 1。

下面是部分结果:

-----------
35         
34         
...

C. 使用 value() 和 exist() 方法从 xml 类型的列中检索值

下面的示例显示同时使用 xml 数据类型的 value() 方法和 exist() 方法。value() 方法用于从 XML 中检索 ProductModelID 属性值。WHERE 子句中的 exist() 方法用于从表中筛选行。

此查询将从把保修信息(<Warranty> 元素)作为功能之一的 XML 实例中检索产品型号 ID。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> 子元素作为功能之一。

  • 然后,SELECT 子句中的 value() 方法将 ProductModelID 属性值作为整数进行检索。

下面是部分结果:

Result     
-----------
19         
23         
...

D. 使用 exist() 方法而不使用 value() 方法

由于性能原因,不在谓词中使用 value() 方法与关系值进行比较,而改用具有 sql:column() 的 exist()。例如:

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