replace value of (XML DML)

適用対象:SQL ServerAzure SQL DatabaseAzure SQL Managed Instance

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

構文

replace value of Expression1   
with Expression2  

Note

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

引数

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

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

replace value of を使用した次の XML DML ステートメントの例は、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 つだけにする必要があります。パス式の末尾に "[1]" を追加して明示的に 1 つのノードを指定します。

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

次の例に示すように、replace value of XML DML ステートメントの 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 列を含むテーブル (T) を AdventureWorks データベースに作成します。 次に、製造手順の XML インスタンスを ProductModel テーブルの Instructions 列からテーブル 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="https://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="https://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="https://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 の使い方に注意してください。 この処理は、値を特定の型にする必要がある場合に必要です。 この例では、値を 500 にした場合、明示的にキャストする必要はありません。

参照

型指定された XML と型指定されていない XML の比較
XML データのインスタンスの作成
xml データ型メソッド
XML データ変更言語 (XML DML)