insert (XML DML)
插入一个或多个由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 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类型的变量。然后,通过一些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分区,但是作为文本节点添加它,一些无效的字符被转换成字符实体。比如说,“<”被保存为<。
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