插入 (XML DML)
将 Expression1 标识的一个或多个节点作为 Expression2 标识的节点的子节点或同级节点插入。
语法
insert
Expression1 (
{as first | as last} into | after | before
Expression2
)
参数
Expression1
标识要插入的一个或多个节点。这可以是一个常量 XML 实例、对应用修改方法的相同 XML 架构集合的类型化 XML 数据类型实例的引用、使用单独的 sql:column()/sql:variable() 函数的非类型化 XML 数据类型实例,或者是一个 XQuery 表达式。该表达式可以得出节点、文本节点或一组有序的节点。但它无法解得根 (/) 节点。如果该表达式得出一个值或一组值,则这些值作为单个文本节点插入,各值之间以空格分隔开。如果将多个节点指定为常量,则这些节点用括号括住,并以逗号分隔开。但无法插入异构序列(如一组元素、属性或值)。如果 Expression1 解得一个空序列,则不会发生插入操作,并且不会返回任何错误。into
Expression1 标识的节点作为 Expression2 标识的节点的直接后代(子节点)插入。如果 Expression2 中的节点已有一个或多个子节点,则必须使用 as first 或 as last 来指定所需的新节点添加位置。例如,分别在子列表的开头或末尾。插入属性时忽略 as first 和 as last 关键字。after
Expression1 标识的节点作为 Expression2 标识的节点的同级节点直接插入在其后面。after 关键字不能用于插入属性。例如,它不能用于插入属性构造函数或从 XQuery 返回属性。before
Expression1 标识的节点作为 Expression2 标识的节点的同级节点直接插入在其前面。before 关键字不能用于插入属性。例如,它不能用于插入属性构造函数或从 XQuery 返回属性。Expression2
标识节点。Expression1 标识的节点是相对于 Expression2 标识的节点插入的。这可以是 XQuery 表达式,返回当前被引用的文档中现有节点的引用。如果返回多个节点,则插入失败。如果 Expression2 返回一个空序列,则不会发生插入操作,并且不会返回任何错误。如果 Expression2 在静态时不是单独的,则将返回静态错误。Expression2 不能是处理指令、注释或属性。请注意,Expression2 必须是文档中现有节点的引用,并且不能是构造的节点。
示例
A. 将元素节点插入文档中
以下示例说明了如何将元素插入文档中。首先,将 XML 文档分配给 xml 类型的变量。然后,示例使用几个 insert XML DML 语句,说明如何将元素节点插入文档中。每次插入后,SELECT 语句都会显示结果。
USE AdventureWorks2008R2;
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]”以要求每次只返回单个目标。这样就确保了只有单个目标节点。
B. 将多个元素插入文档中
在以下示例中,首先将文档分配给 xml 类型的变量。然后,将包括两个元素(代表产品功能)的序列分配给第二个 xml 类型的变量,再将此序列插入第一个变量。
USE AdventureWorks2008R2;
GO
DECLARE @myDoc xml;
SET @myDoc = N'<Root>
<ProductDescription ProductID="1" ProductName="Road Bike">
<Features> </Features>
</ProductDescription>
</Root>';
DECLARE @newFeatures xml;
SET @newFeatures = N'<Warranty>1 year parts and labor</Warranty>
<Maintenance>3 year parts and labor extended maintenance is available</Maintenance>';
-- insert new features from specified variable
SET @myDoc.modify('
insert sql:variable("@newFeatures")
into (/Root/ProductDescription/Features)[1] ')
SELECT @myDoc;
GO
C. 将属性插入文档中
以下示例说明了如何将属性插入文档中。首先,将文档分配给 xml 类型的变量。然后,使用一系列 insert XML DML 语句将属性插入文档中。每次插入属性后,SELECT 语句都会显示结果。
USE AdventureWorks2008R2;
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 AdventureWorks2008R2;
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 AdventureWorks2008R2;
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 AdventureWorks2008R2;
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
查询将文本节点插入 <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 AdventureWorks2008R2;
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 AdventureWorks2008R2;
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] 来显式指定。
-- check the update
SELECT x.query(' //ProductDescription/Features')
FROM T;
GO
I. 根据 if 条件语句进行插入
在以下示例中,将 if 条件语句指定为 insert XML DML 语句中 Expression1 的一部分。如果条件为 True,则将属性添加到 <WorkCenter> 元素中。
USE AdventureWorks2008R2;
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> 子元素少于或等于两个,则在文档中插入元素。
USE AdventureWorks2008R2;
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 中。
在该示例中,首先在 AdventureWorks2008R2 数据库中创建带有类型化的 xml 列的表 (T)。然后将一个生产说明 XML 实例从 ProductModel 表的 Instructions 列复制到表 T 中。随后再对表 T 中的 XML 内容应用插入操作。
USE AdventureWorks2008R2;
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