替换 (XML DML) 的值

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

在文档中更新节点的值。

语法

replace value of Expression1
with Expression2

注意

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

参数

Expression1

标识其值要更新的节点。 它必须仅标识一个单个节点。 即 Expression1 必须是一个静态的单一实例。 如果键入 XML,则节点的类型必须是一个简单的 类型。 如果选择了多个节点,则会出现错误。 如果 Expression1 返回一个空序列,不会发生值替换,也不返回错误。 Expression1 必须返回具有简单类型内容(列表或原子类型)的单个元素、文本节点或属性节点。 Expression1 不可能是联合类型、复杂类型、处理指令、文档节点或注释节点,否则会返回错误。

Expression2

标识节点的新值。 它可以是返回简单类型节点的表达式,因为 data() 隐式使用。 如果该值是值列表,则语句会将 update 旧值替换为列表。 修改类型化的 XML 实例时,Expression2 必须是相同的类型或 Expression1子类型。 否则,将返回错误。 修改非类型化的 XML 实例时, Expression2 必须是可以原子化的表达式。 否则,将返回错误。

示例

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

XML DML 语句的 replace value of 以下示例说明了如何更新 XML 文档中的节点。

A. 替换 XML 实例中的值

在以下示例中,首先将文档实例分配给 xml 类型的变量。 然后, replace value of XML DML 语句更新文档中的值。

DECLARE @myDoc XML;

SET @myDoc = '<Root>
<Location LocationID="10"
            LaborHours="1.1"
            MachineHours=".2" >Manufacturing steps are described here.
<step>Manufacturing step 1 at this work center</step>
<step>Manufacturing step 2 at this work center</step>
</Location>
</Root>';

SELECT @myDoc;

-- update text in the first manufacturing step
SET @myDoc.modify('
  replace value of (/Root/Location/step[1]/text())[1]
  with "new text describing the manu step"
');

SELECT @myDoc;

-- update attribute value
SET @myDoc.modify('
  replace value of (/Root/Location/@LaborHours)[1]
  with "100.0"
');

SELECT @myDoc;

要更新的目标最多必须是一个通过在表达式的结尾添加“[1]”在路径表达式中显式指定的节点。

B. 使用 if 表达式确定替换值

可以在语句的 replace value of Expression2指定if表达式,如以下示例所示。 Expression1 标识 LaborHours 要更新第一个工作中心的属性。 Expression2 使用 if 表达式来确定属性的新值 LaborHours

DECLARE @myDoc XML;
SET @myDoc = '<Root>
<Location LocationID="10"
            LaborHours=".1"
            MachineHours=".2" >Manu steps are described here.
<step>Manufacturing step 1 at this work center</step>
<step>Manufacturing step 2 at this work center</step>
</Location>
</Root>';

--SELECT @myDoc
SET @myDoc.modify('
  replace value of (/Root/Location[1]/@LaborHours)[1]
  with (
       if (count(/Root/Location[1]/step) > 3) then
         "3.0"
       else
          "1.0"
      )
');

SELECT @myDoc;

°C 更新存储在非类型化的 XML 列中的 XML

以下示例更新存储在列中的 XML:

DROP TABLE T;
GO

CREATE TABLE T (i INT, x XML);
GO

INSERT INTO T
VALUES (
    1,
    '<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>'
);
GO

-- verify the current <ProductDescription> element
SELECT x.query(' /Root/ProductDescription')
FROM T;

-- update the ProductName attribute value
UPDATE T
SET x.modify('
  replace value of (/Root/ProductDescription/@ProductName)[1]
  with "New Road Bike" ');

-- verify the update
SELECT x.query(' /Root/ProductDescription');
FROM T

D. 更新存储在类型化的 XML 列中的 XML

此示例替换存储在类型化的 XML 列中的生产说明文档中的值。

在本示例中,首先在数据库中创建一个具有类型化的 XML 列的AdventureWorks2022表(T)。 然后,将生产指令 XML 实例从 Instructions 表中的 ProductModel 列复制到表中 T。 然后,插入将应用于表中 T的 XML。

USE AdventureWorks2022;
GO

DROP TABLE T;
GO

CREATE TABLE T (
    ProductModelID INT PRIMARY KEY,
    Instructions XML(Production.ManuInstructionsSchemaCollection)
);
GO

INSERT T
SELECT ProductModelID, Instructions
FROM Production.ProductModel
WHERE ProductModelID = 7;
GO

--insert a new location - <Location 1000/>.
UPDATE T
SET Instructions.modify('
  declare namespace MI="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
insert <MI:Location LocationID="1000"  LaborHours="1000"  LotSize="1000" >
           <MI:step>Do something using <MI:tool>hammer</MI:tool></MI:step>
         </MI:Location>
  as first
  into (/MI:root)[1]
');
GO

SELECT Instructions
FROM T;
GO

-- Now replace manu. tool in location 1000
UPDATE T
SET Instructions.modify('
  declare namespace MI="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
  replace value of (/MI:root/MI:Location/MI:step/MI:tool)[1]
  with "screwdriver"
');
GO

SELECT Instructions
FROM T;

-- Now replace value of lot size
UPDATE T
SET Instructions.modify('
  declare namespace MI="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
  replace value of (/MI:root/MI:Location/@LotSize)[1]
  with 500 cast as xs:decimal ?
');
GO

SELECT Instructions
FROM T;

此示例在替换LotSize值时使用castcast 如果值必须具有特定类型,则为必需值。 在此示例中,如果 500 为值,则不需要显式强制转换。