replace value of (XML DML)

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

構文

replace value of 
      Expression1 
with
      Expression2

引数

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

  • Expression2
    ノードの新しい値を特定します。暗黙的に data() が使用されるので、この式を単純型に型指定されたノードを返す式にできます。この値が値リストの場合、update ステートメントにより、古い値がそのリストと置き換えられます。型指定された XML インスタンスを変更する場合、Expression2 は Expression1 と同じ型またはサブタイプにする必要があります。それ以外の型を指定すると、エラーが返されます。型指定されていない 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 AdventureWorks
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 にした場合、明示的にキャストする必要はありません。