insert (XML DML)

>本主题适用于: SQL Server (starting with 2008) Azure SQL Database Azure SQL Data Warehouse Parallel Data Warehouse

插入一个或多个由Expression1标识的节点,作为由Expression2标识的节点的子节点或同辈节点。

句法

insert
      Expression1 (
                 {as first | as last} into | after | before
                                    Expression2
                )

参数

Expression1
标识一个或多个要插入的节点。它可以是一个常量XML实例;或者是一个类型化的XML数据类型实例的一个引用,数据实例是应用修改方法的那个XML架构集合上的数据实例;或者是一个非类型化的XML数据实例,使用独立的sql:column()/sql:variable()函数;或者是一个XQuery表达式。该表达式可以产生一个节点,也可以是一个文本节点,或者一个有序的节点序列。它不能分解到根节点(/)。如果这个表达式产生一个值或者一系列值,值会作为简单文本节点插入,有空格分开序列中的每个值。如果你指定多个节点作为常量,要用括号包围节点,并用逗号分开它们。你不能插入异构序列,比如说元素的序列、属性的序列或值的序列。如果Expression1分解到一个空序列,就不会插入,也不会返回错误。
into
插入Expression1所标识的节点,作为Expression2所标识的节点的一个直接后代(子节点)。如果Expression2内部已经有一个或多个子节点,你一定要使用as firstas last,以指明你想把新节点添加到哪里。两者分别表示把新节点插入到子节点列表的开头和末尾。如果是插入属性,会忽略掉as firstas last关键词。
after
插入Expression1所标识的节点,作为Expression2所标识的节点的同辈节点,直接插在它后面。插入属性不能使用after关键词。比如说,它不能用于插入一个属性构造器,或者从一个XQuery返回一个属性。
before
插入Expression1所标识的节点,作为Expression2所标识的节点的同辈节点,直接插在它前面。插入属性不能使用before关键词。比如说,它不能用于插入一个属性构造器,或者从一个XQuery返回一个属性。
Expression2
标识一个节点。插入Expression1所标识的节点是相对于Expression2所标识的节点的。它可是是一个XQuery表达式,返回对一个已经存在在当前引用文档中的节点的引用。如果返回了不止一个节点,就会插入失败。如果Expression2返回一个空序列,就不会插入,也不会返回错误。如果Expression2是静态的,不是一个单例模型,就会返回一个静态错误。Expression2不能是一个正在处理的指令、注释,或者一个属性。注意Expression2必须是对一个在文档中已经存在的节点的引用,不能是一个构造得的节点。

示例

A. 向文档中插入一个元素节点

下面的示例演示了如何向一个文档插入节点。首先,把一个XML文档指派为xml类型的变量。然后,通过一些insertXML DML语句,该示例演示如何在文档中插入元素节点。在每次插入之后,SELECT语句显示了结果。

USE AdventureWorks;
GO
DECLARE @myDoc xml;
SET @myDoc = '<Root>
    <ProductDescription ProductID="1" ProductName="Road Bike">
        <Features>
        </Features>
    </ProductDescription>
</Root>'  ;
SELECT @myDoc;
-- 插入第一个特征子节点(不需要指定as first或as last)
SET @myDoc.modify('
insert <Maintenance>3 year parts and labor extended maintenance is available</Maintenance>
into (/Root/ProductDescription/Features)[1]') ;
SELECT @myDoc ;
-- 插入第二个特征子节点。我们想让它成为序列的第一个,所以使用了'as first'
set @myDoc.modify('
insert <Warranty>1 year parts and labor</Warranty>
as first
into (/Root/ProductDescription/Features)[1]
')  ;
SELECT @myDoc  ;
-- 插入第三个特征子节点。为了让它成为<Features>的最后一个子节点,用了'as last'
SET @myDoc.modify('
insert <Material>Aluminium</Material>
as last
into (/Root/ProductDescription/Features)[1]
')
SELECT @myDoc ;
-- 插入第四个特征,这次是作为同辈节点(不再是一个子节点)
-- 使用了'after'关键词(而不是使用as first或as last关键词)
set @myDoc.modify('
insert <BikeFrame>Strong long lasting</BikeFrame>
after (/Root/ProductDescription/Features/Material)[1]
')  ;
SELECT @myDoc;
GO

注意,在示例不的变量路径表达式指定了“[1]”作为预静态类型要求。这确保了只有一个目标节点。

B. 向文档中插入多个元素

在下面的示例中,把一个文档指派为一个xml类型的变量。然后,把一个序列指派为第二个xml类型的变量,序列中包含两个元素,代表了产品的两个特征。然后把这个序列插入到第一个变量中。

USE AdventureWorks;
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>';
-- 从指定的序列中插入新特征
SET @myDoc.modify('
insert sql:variable("@newFeatures")
into (/Root/ProductDescription/Features)[1] ')
SELECT @myDoc;
GO

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  ;
-- 插入LaborHours属性
SET @myDoc.modify('
insert attribute LaborHours {".5" }
into (/Root/Location[@LocationID=10])[1] ') ;
SELECT @myDoc  ;
-- 插入MachineHour属性,但是它的值来自于一个SQL变量@Hrs
DECLARE @Hrs float ;
SET @Hrs =.2   ;
SET @myDoc.modify('
insert attribute MachineHours {sql:variable("@Hrs") }
into   (/Root/Location[@LocationID=10])[1] ');
SELECT @myDoc;
-- 插入一系列属性节点(注意使用“,”,并用圆括号包围那几个属性)
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分区,但是作为文本节点添加它,一些无效的字符被转换成字符实体。比如说,“&lt;”被保存为<。

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
-- 插入一个新元素
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条件语句插入内容

在下面的示例中,在insert XML DML语句中,指定了一个IF条件作为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

下面的示例很相似,除了insert XML DML语句在条件为True时向文档插入一个元素。也就是说,如果<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数据库中创建一个表(T),它带有一个类型化的xml列。然后你把产品说明书XML实例从ProductModel表的Instructions列复制到表T中。然后对表T应用插入。

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;
-- 现在插入开始
--1) 插入一个新Location。在insert()中作为expression2指定的<Root>一定得是单例模型。
UPDATE T
set Instructions.modify('
declare namespace MI="http://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) 在新的<Location>中插入属性
UPDATE T
SET Instructions.modify('
declare namespace MI="http://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
--清理
DROP TABLE T ;
GO

如果你喜欢这篇文章,敬请给站长打赏↑

除特别注明外,本站所有文章均为本站站长原译,转载请注明出处。