插入 (XML DML)
将 Expression1 标识的一个或多个节点作为 Expression2 标识的节点的子节点或同级节点插入。
语法
insert
Expression1 (
{as first | as last} into | after | before
Expression2
)
参数
- Expression1
标识要插入的一个或多个节点。它可以是常量 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 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]”以要求每次只返回单个目标。这样就确保了只有单个目标节点。
B. 将多个元素插入文档中
在以下示例中,首先将文档分配给 xml 类型的变量。然后,向文档中插入一个包括两个元素(产品功能)的序列。
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
查询将文本节点插入 <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] 来显式指定。
-- check the update
SELECT x.query(' //ProductDescription/Features')
FROM T;
GO
I. 根据 if 条件语句进行插入
在以下示例中,将 if 条件语句指定为 insert XML DML 语句中 Expression1 的一部分。如果条件为 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
> 子元素少于或等于两个,则在文档中插入元素。
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 中。
在此示例中,首先在 AdventureWorks 数据库中创建一个包含类型化的 xml 列的表 (T)。然后将一个生产说明 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 应用程序