insert (XML DML)

Вставляет один или несколько узлов, идентифицируемых выражением Expression1 в качестве дочерних узлов или одноуровневых элементов с общим родителем для узла, идентифицируемого выражением Expression2.

Применимо для следующих объектов: SQL Server (SQL Server 2008 по текущую версию), База данных SQL Windows Azure (С первоначального выпуска по текущий выпуск).

Синтаксис

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 должно представлять собой ссылку на существующий узел в документе, а не на конструируемый узел.

Примеры

А.Вставка узлов элементов в документ

В следующем примере показана вставка элементов в документ. Сначала XML-документ присваивается переменной типа xml. Затем с помощью нескольких XML-DML-инструкций insert демонстрируется вставка узлов элементов в документ. После каждой операции вставки с помощью инструкции 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]». Это позволяет гарантированно указать отдельный целевой узел.

Б.Вставка нескольких элементов в документ

В следующем примере документу сначала назначается переменная типа 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>';         
-- insert new features from specified variable          
SET @myDoc.modify('           
insert sql:variable("@newFeatures")           
into (/Root/ProductDescription/Features)[1] ')           
SELECT @myDoc;
GO

В.Вставка атрибутов в документ

В следующем примере показано, как выполняется вставка атрибутов в документ. Сначала документ присваивается переменной типа xml. Затем используется серия XML-DML-инструкций insert для вставки атрибутов в документ. После каждой операции вставки с помощью инструкции 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

Г.Вставка узла с комментарием

В этом запросе XML-документ сначала присваивается переменной типа xml. Затем для вставки узла с комментарием после первого элемента <step> используется язык 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 <!-- some comment -->           
after (/Root/Location[@LocationID=10]/step[1])[1] ');          
SELECT @myDoc;
GO

Д.Вставка инструкции по обработке

В этом запросе 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

Е.Вставка данных с помощью раздела 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> &lt;notxml&gt; as text &lt;/notxml&gt; or cdata </Features>
</ProductDescription>
</Root>     

Ж.Вставка текстового узла

В этом запросе XML-документ сначала присваивается переменной типа xml. Затем для вставки текстового узла в качестве первого дочернего узла элемента <Root> используется язык XML DML. Для указания текста используется текстовый конструктор.

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;

З.Вставка нового элемента в нетипизированный 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

И.Вставка на основе инструкции с условием

В следующем примере в XML-DML-инструкции insert в качестве части выражения 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

Ниже приведен похожий пример, отличающийся только тем, что XML-DML-инструкцией insert выполняется вставка не атрибута, а элемента в документ в случае, если условие возвращает значение 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>

К.Вставка узлов в типизированный XML-столбец

В данном примере выполняется вставка элемента и атрибута в производственную инструкцию в формате XML, хранящуюся в типизированном столбце типа xml.

В данном примере следует сначала создать в базе данных AdventureWorks таблицу (T) с типизированным столбцом типа xml. Затем копируются производственные инструкции экземпляра XML из столбца Instructions таблицы ProductModel в таблицу T. После этого вставленные данные применяются к XML в таблице 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;
-- 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 DML)

Другие ресурсы

Методы типа данных XML