replace value of (XML DML)

適用対象: SQL Server Azure SQL データベース Azure SQL Managed Instance

ドキュメント内のノードの値を更新します。

構文

replace value of Expression1
with Expression2

Note

SQL Server 2014 (12.x) 以前のバージョンの Transact-SQL 構文を確認するには、以前のバージョンのドキュメントを参照してください。

引数

Expression1

値を更新するノードを特定します。 ノードを 1 つだけ指定する必要があります。 つまり、Expression1 は静的なシングルトンである必要があります。 XML が型指定されている場合、ノードの型は simple 型である必要があります。 複数のノードを選択すると、エラーが発生します。 Expression1 が空のシーケンスを返す場合は、値の置換は行われず、エラーは返されません。 Expression1 からは、単純型に型指定された内容 (リストまたはアトミック型)、テキスト ノード、または属性ノードを持つ 1 つの要素が返される必要があります。 Expression1 に共用体型、複合型、処理命令、ドキュメント ノード、またはコメント ノードを指定することはできません。指定すると、エラーが返されます。

Expression2

ノードの新しい値を特定します。 data()は暗黙的に使用されるため、単純型ノードを返す式を指定できます。 値が値のリストの場合、 update ステートメントは古い値をリストに置き換えます。 型指定された XML インスタンスを変更する場合、 Expression2 は同じ型であるか、 Expression1のサブタイプである必要があります。 それ以外の場合は、エラーが返されます。 型指定されていない XML インスタンスを変更する場合、 Expression2 はアトミック化できる式である必要があります。 それ以外の場合は、エラーが返されます。

この記事の Transact-SQL コード サンプルは AdventureWorks2022 または AdventureWorksDW2022 サンプル データベースを使用します。このサンプル データベースは、Microsoft SQL Server サンプルとコミュニティ プロジェクトのホーム ページからダウンロードできます。

replace value of XML DML ステートメントの次の例は、XML ドキュメント内のノードを更新する方法を示しています。

A. XML インスタンス内の値を置き換える

次の例では、まず、ドキュメント インスタンスが xml 型の変数に代入されます。 次に、XML DML ステートメント replace value of ドキュメント内の値を更新します。

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 つだけにする必要があります。パス式の末尾に "[1]" を追加して明示的に 1 つのノードを指定します。

B. if 式を使用して置換値を決定する

次の例に示すように、replace value of ステートメントの Expression2if式を指定できます。 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 列に格納されている製造手順ドキュメント内の値を置換します。

この例では、最初に、AdventureWorks2022 データベースに型指定された XML 列を含むテーブル (T) を作成します。 次に、ProductModel テーブルのInstructions列から製造指示 XML インスタンスをテーブル 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値を置き換えるときにcastを使用します。 cast は、値が特定の型である必要がある場合に必要です。 この例では、 500 が値の場合、明示的なキャストは必要ありません。