insert (XML DML)
Expression1 で識別される 1 つ以上のノードを、Expression2 で識別されるノードの子ノードまたは兄弟ノードとして挿入します。
構文
insert
Expression1 (
{as first | as last} into | after | before
Expression2
)
引数
- Expression1
挿入する 1 つ以上のノードを識別します。XML の定数インスタンスまたは XQuery 式を指定できます。式の結果は、ノード、テキスト ノード、または順序付けられたノードのシーケンスになります。式をルート (/) ノードに解決することはできません。式の結果が 1 つの値または値のシーケンスになる場合、シーケンス内の各値がスペースで区切られた 1 つのテキスト ノードとして値が挿入されます。複数のノードを定数として指定する場合は、ノードをかっこで囲み、コンマで区切ります。一連の要素、属性、値などの異種シーケンスは挿入できません。Expression1 が空のシーケンスに解決される場合は、挿入が行われず、エラーも返されません。
- into
Expression1 で識別されるノードは、Expression2 で識別されるノードの直接の子孫 (子ノード) として挿入されます。Expression2 のノードに既に 1 つ以上の子ノードが含まれている場合、as first または as last のいずれかを使用して、新しいノードを追加する場所を指定する必要があります。たとえば、それぞれ子リストの先頭または末尾を指定します。属性を挿入するときは、as first キーワードと as last キーワードは無視されます。
- after
Expression1 で識別されるノードが、Expression2 で識別されるノードの直後に兄弟として挿入されます。after キーワードを使用して属性を挿入することはできません。たとえば、このキーワードを指定して、属性コンストラクタを挿入したり、XQuery から属性を返すことはできません。
- before
Expression1 で識別されるノードが、Expression2 で識別されるノードの直前に兄弟として挿入されます。属性を挿入するときは、before キーワードを使用できません。たとえば、このキーワードを指定して、属性コンストラクタを挿入したり、XQuery から属性を返すことはできません。
- Expression2
ノードを識別します。Expression2 で識別されるノードの相対位置に、Expression1 で識別されるノードが挿入されます。現在参照されているドキュメントに存在するノードへの参照を返す XQuery 式も使用できます。複数のノードが返されると、挿入は失敗します。Expression2 で空のシーケンスが返されると、挿入が行われず、エラーも返されません。Expression2 が静的に単一にならないと、静的エラーが返されます。Expression2 を、処理命令、コメント、または属性にはできません。Expression2 は、構築されたノードではなく、ドキュメント内の既存のノードへの参照にする必要があります。
例
A. ドキュメントへの要素ノードの挿入
次の例は、ドキュメントに要素を挿入する方法を示します。まず、XML ドキュメントが xml 型の変数に代入されます。次に、いくつかの insert XML DML ステートメントを使用して、要素ノードをドキュメントに挿入する方法を示します。それぞれの挿入後、SELECT ステートメントによって結果が表示されます。
USE AdventureWorks;
GO
DECLARE @myDoc xml
SET @myDoc = '<Root>
<ProductDescription ProductID="1" ProductName="Road Bike">
<Features>
</Features>
</ProductDescription>
</Root>'
SELECT @myDoc
-- insert first feature child (no need to specify as first or as last)
SET @myDoc.modify('
insert <Maintenance>3 year parts and labor extended maintenance is available</Maintenance>
into (/Root/ProductDescription/Features)[1]')
SELECT @myDoc
-- insert second feature. We want this to be the first in sequence so use 'as first'
set @myDoc.modify('
insert <Warranty>1 year parts and labor</Warranty>
as first
into (/Root/ProductDescription/Features)[1]
')
SELECT @myDoc
-- insert third feature child. This one is the last child of <Features> so use 'as last'
SELECT @myDoc
SET @myDoc.modify('
insert <Material>Aluminium</Material>
as last
into (/Root/ProductDescription/Features)[1]
')
SELECT @myDoc
-- Add fourth feature - this time as a sibling (and not a child)
-- 'after' keyword is used (instead of as first or as last child)
SELECT @myDoc
set @myDoc.modify('
insert <BikeFrame>Strong long lasting</BikeFrame>
after (/Root/ProductDescription/Features/Material)[1]
')
SELECT @myDoc;
GO
この例のさまざまなパス式では、静的な型指定要件ごとに "[1]" が指定されています。これにより、対象ノードを 1 つにしています。
B. ドキュメントへの複数の要素の挿入
次の例では、まず、ドキュメントが xml 型の変数に代入されます。次に、2 つの要素 (製品の機能) のシーケンスが挿入されます。
USE AdventureWorks;
GO
DECLARE @myDoc xml
SET @myDoc = '<Root>
<ProductDescription ProductID="1" ProductName="Road Bike">
<Features> </Features>
</ProductDescription>
</Root>'
SELECT @myDoc
-- insert first feature children (no need to specify as first or last)
SET @myDoc.modify('
insert (
<Warranty>1 year parts and labor</Warranty>,
<Maintenance>3 year parts and labor extended maintenance is available</Maintenance>
)
into (/Root/ProductDescription/Features)[1] ')
SELECT @myDoc;
GO
シーケンス内の要素ノードはコンマで区切られ、かっこで囲まれています。これで XQuery でシーケンスを構築する方法が決まります。
C. ドキュメントへの属性の挿入
次の例では、属性をドキュメントに挿入する方法について説明します。まず、xml 型の変数にドキュメントが代入されます。次に、一連の insert XML DML ステートメントを使用して、ドキュメントに属性が挿入されます。各属性の挿入後、SELECT ステートメントによって結果が表示されます。
USE AdventureWorks;
GO
DECLARE @myDoc xml
SET @myDoc =
'<Root>
<Location LocationID="10" >
<step>Manufacturing step 1 at this work center</step>
<step>Manufacturing step 2 at this work center</step>
</Location>
</Root>'
SELECT @myDoc
-- insert LaborHours attribute
SET @myDoc.modify('
insert attribute LaborHours {".5" }
into (/Root/Location[@LocationID=10])[1] ')
SELECT @myDoc
-- insert MachineHours attribute but its value is retrived from a sql variable @Hrs
DECLARE @Hrs float
SET @Hrs =.2
SET @myDoc.modify('
insert attribute MachineHours {sql:variable("@Hrs") }
into (/Root/Location[@LocationID=10])[1] ')
SELECT @myDoc
-- insert sequence of attribute nodes (note the use of ',' and ()
-- around the attributes.
SET @myDoc.modify('
insert (
attribute SetupHours {".5" },
attribute SomeOtherAtt {".2"}
)
into (/Root/Location[@LocationID=10])[1] ')
SELECT @myDoc;
GO
D. コメント ノードの挿入
次のクエリでは、まず、XML ドキュメントが xml 型の変数に代入されます。次に、XML DML を使用して、最初の <step
> 要素の後にコメント ノードを挿入します。
USE AdventureWorks;
GO
DECLARE @myDoc xml
SET @myDoc =
'<Root>
<Location LocationID="10" >
<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('
insert <!-- some comment -->
after (/Root/Location[@LocationID=10]/step[1])[1] ')
SELECT @myDoc;
GO
E. 処理命令の挿入
次のクエリでは、まず、XML ドキュメントが xml 型の変数に代入されます。次に、XML DML キーワードを使用して、ドキュメントの先頭に処理命令が挿入されます。
USE AdventureWorks;
GO
DECLARE @myDoc xml
SET @myDoc =
'<Root>
<Location LocationID="10" >
<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('
insert <?Program="Instructions.exe" ?>
before (/Root)[1] ')
SELECT @myDoc ;
GO
F. CDATA セクションを使用したデータの挿入
< や > など、XML では無効な文字が含まれるテキストを挿入するときは、次のクエリに示すように、CDATA セクションを使用してデータを挿入できます。クエリでは CDATA セクションが指定されていますが、無効な文字はエンティティに変換され、テキスト ノードとして追加されます。たとえば、'<' は < として保存されます。
USE AdventureWorks;
GO
DECLARE @myDoc xml
SET @myDoc =
'<Root>
<ProductDescription ProductID="1" ProductName="Road Bike">
<Features> </Features>
</ProductDescription>
</Root>'
SELECT @myDoc
SET @myDoc.modify('
insert <![CDATA[ <notxml> as text </notxml> or cdata ]]>
into (/Root/ProductDescription/Features)[1] ')
SELECT @myDoc ;
GO
クエリでは、1 つのテキスト ノードが <Features
> 要素に挿入されます。
<Root>
<ProductDescription ProductID="1" ProductName="Road Bike">
<Features> <notxml> as text </notxml> or cdata </Features>
</ProductDescription>
</Root>
G. テキスト ノードの挿入
次のクエリでは、まず、XML ドキュメントが xml 型の変数に代入されます。次に、XML DML が使用され、<Root
> 要素の最初の子としてテキスト ノードが挿入されます。テキスト コンストラクタを使用して、テキストを指定します。
USE AdventureWorks;
GO
DECLARE @myDoc xml
SET @myDoc = '<Root>
<ProductDescription ProductID="1" ProductName="Road Bike">
<Features>
</Features>
</ProductDescription>
</Root>'
SELECT @myDoc
set @myDoc.modify('
insert text{"Product Catalog Description"}
as first into (/Root)[1]
')
SELECT @myDoc
H. 型指定されていない xml 列への新しい要素の挿入
次の例では、XML DML を適用して、xml 型の列に格納された XML インスタンスを更新します。
USE AdventureWorks;
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
-- insert a new element
UPDATE T
SET x.modify('insert <Material>Aluminium</Material> as first
into (/Root/ProductDescription/Features)[1]
');
GO
この場合も、<Material
> 要素ノードが挿入されるときは、パス式が 1 つの対象を返す必要があります。これは、式の最後に [1] を追加することにより、明示的に指定します。
-- check the update
SELECT x.query(' //ProductDescription/Features')
FROM T;
GO
I. IF 条件ステートメントに基づいた挿入
次の例では、insert XML DML ステートメント内の Expression1 の一部に IF 条件が指定されます。条件が True の場合、<WorkCenter
> 要素に属性が追加されます。
USE AdventureWorks;
GO
DECLARE @myDoc xml
SET @myDoc =
'<Root>
<Location LocationID="10" LaborHours="1.2" >
<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('
insert
if (/Root/Location[@LocationID=10])
then attribute MachineHours {".5"}
else ()
as first into (/Root/Location[@LocationID=10])[1] ')
SELECT @myDoc;
GO
次の例も同様ですが、条件が True の場合に insert XML DML ステートメントによってドキュメントに要素が挿入されます。つまり、<WorkCenter
> 要素に含まれる <step
> 子要素が 2 つ以下の場合に挿入されます。
USE AdventureWorks;
GO
DECLARE @myDoc xml
SET @myDoc =
'<Root>
<Location LocationID="10" LaborHours="1.2" >
<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('
insert
if (count(/Root/Location/step) <= 2)
then element step { "This is a new step" }
else ()
as last into (/Root/Location[@LocationID=10])[1] ')
SELECT @myDoc;
GO
次に結果を示します。
<Root>
<WorkCenter WorkCenterID="10" LaborHours="1.2">
<step>Manufacturing step 1 at this work center</step>
<step>Manufacturing step 2 at this work center</step>
<step>This is a new step</step>
</WorkCenter>
J. 型指定された 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
SELECT Instructions
FROM T;
-- now insertion begins
--1) insert a new manu. Location. The <Root> specified as
-- expression 2 in the insert() must be singleton.
UPDATE T
set Instructions.modify('
declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
insert <MI:Location LocationID="1000" >
<MI:step>New instructions go here</MI:step>
</MI:Location>
as first
into (/MI:root)[1]
')
SELECT Instructions
FROM T ;
-- 2) insert attributes in the new <Location>
UPDATE T
SET Instructions.modify('
declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
insert attribute LaborHours { "1000" }
into (/MI:root/MI:Location[@LocationID=1000])[1] ');
GO
SELECT Instructions
FROM T ;
GO
--cleanup
DROP TABLE T ;
GO
参照
概念
型指定された XML と型指定されていない XML
xml データ型
XML インスタンスの生成
XML DML (XML データ変更言語)
サンプル XML アプリケーション