(XML DML) の値を置き換える

適用対象:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceMicrosoft Fabric の SQL データベース

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

構文

replace value of Expression1
with Expression2

引数

Expression1

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

Expression2

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

例

この記事のコードサンプルは、Azure Data SQL Samples Repository GitHub repositoryからダウンロードできるAdventureWorks2025またはAdventureWorksDW2025サンプルデータベースを使用しています。

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 式を使用して置換値を決定する

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

この例では、最初に、T データベースに型指定された XML 列を含むテーブル (AdventureWorks2025) を作成します。 次に、Instructions テーブルのProductModel列から製造指示 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;

この例では、cast値を置き換えるときにLotSizeを使用します。 cast は、値が特定の型である必要がある場合に必要です。 この例では、 500 が値の場合、明示的なキャストは必要ありません。