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