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

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例

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

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

语法

value ( XQuery , SQLType )

注意

若要查看 SQL Server 2014 (12.x) 及更早版本的 Transact-SQL 语法,请参阅早期版本文档

参数

XQuery

XQuery 表达式是一个字符串文本,用于检索 XML 实例中的数据。 XQuery 必须最多返回一个值。 否则,将返回错误。

SQLType

要返回的首选 SQL 类型(字符串文本)。 此方法的返回类型与 SQLType 参数匹配。 SQLType 可以是用户定义的 SQL 数据类型。

注意

SQLType 不能是以下数据类型之一:xmlimagetext、ntextsql_variant 或公共语言运行时(CLR)用户定义的类型。

该方法 value() 隐式使用 Transact-SQL CONVERT 运算符。 value() 尝试将 XQuery 表达式的结果(序列化字符串表示形式)从 XML 架构定义 (XSD) 类型转换为 Transact-SQL 转换指定的相应 SQL 类型。 有关类型转换规则 CONVERT的详细信息,请参阅 CAST 和 CONVERT

出于性能原因,可以使用exist()sql:column()谓词中的方法,而不是使用value()谓词中的方法,以与关系值进行比较。 本文稍后将介绍此示例 exist()

示例

本文中的 Transact-SQL 代码示例使用 AdventureWorks2022 示例数据库,可从 Microsoft SQL Server 示例和社区项目主页下载它。

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] 添加到路径表达式的末尾。 有关静态类型化的详细信息,请参阅 XQuery 与静态类型化

B. 使用 value() 方法从 XML 类型列检索整数值

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

SELECT CatalogDescription.value(
    'declare namespace PD="http://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 关键字用于定义命名空间前缀。

  • 对于每个静态类型化要求,都在 [1] 方法的路径表达式结尾处添加 value() 以显式指示路径表达式返回 1。

下面是结果集。

35
34
28
25
23
19

°C 使用 value() 方法从 XML 类型列检索字符串值

针对数据库中的 xml 类型列 (CatalogDescriptionAdventureWorks2022 指定以下查询。 查询从列中存储的每个 XML 实例中检索 ProductModelName 属性值。

SELECT CatalogDescription.value(
    'declare namespace PD="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
       (/PD:ProductDescription/@ProductModelName)[1]', 'varchar(50)') AS Result
FROM Production.ProductModel
WHERE CatalogDescription IS NOT NULL
ORDER BY Result DESC;

上一个查询中的注释:

  • namespace 关键字用于定义命名空间前缀。

  • 对于每个静态类型化要求,都在 [1] 方法的路径表达式结尾处添加 value() 以显式指示路径表达式返回 1。

下面是结果集。

Touring-2000
Touring-1000
Road-450
Road-150
Mountain-500
Mountain 100

D. 使用 value() 和 exist() 方法从 XML 类型列检索值

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

此查询将从把保修信息(<<Warranty> 元素)作为功能之一的 XML 实例中检索产品型号 ID。 WHERE 子句中的条件使用 exist() 方法仅检索满足该条件的行。

SELECT CatalogDescription.value(
    'declare namespace PD="http://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="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
     declare namespace wm="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain";

     /PD:ProductDescription/PD:Features/wm:Warranty') = 1;

上一个查询中的注释:

  • CatalogDescription 列是类型化的 XML 列。 这意味着它具有与其相关的架构集合。 在 Modules 和 Prologs - XQuery Prolog 中,命名空间声明用于定义查询正文稍后使用的前缀。

  • exist()如果该方法返回 1 (true),则表示 XML 实例将子元素作为特征之一包含在<Warranty>内。

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

下面是部分结果:

19
23
...

E. 使用 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/@a)[1]', 'integer') = c1;
GO

可按如下所示重写此代码:

SELECT c1, c2, c3
FROM T
WHERE c3.exist('/root[@a=sql:column("c1")]') = 1;
GO