insert (XML DML)
Inserisce uno o più nodi identificati da Expression1 come nodi figlio o nodi di pari livello del nodo identificato da Expression2.
Sintassi
insert
Expression1 (
{as first | as last} into | after | before
Expression2
)
Argomenti
Expression1
Identifica uno o più nodi da inserire. Può trattarsi di un'istanza XML costante, un riferimento a un'istanza del tipo di dati XML tipizzata dello stesso insieme di schemi XML in cui viene applicato il metodo modify, un'istanza del tipo di dati XML non tipizzata che utilizza una funzione sql:column()/sql:variable() autonoma o un'espressione XQuery. L'espressione può restituire un nodo, anche un nodo di testo, o una sequenza ordinata di nodi, ma non può essere risolta nel nodo radice (/). Se l'espressione restituisce un valore o una sequenza di valori, tali valori vengono inseriti come un nodo di testo nel quale ogni valore della sequenza è separato da uno spazio. Se si specificano più nodi come costante, i nodi vengono racchiusi tra parentesi e sono separati da virgole. Non è possibile inserire sequenze eterogenee, ad esempio una sequenza di elementi, attributi o valori. Se Expression1 viene risolta in una sequenza vuota, non viene inserito nulla e non vengono restituiti errori.into
I nodi identificati da Expression1 vengono inseriti come discendenti diretti (nodi figlio) del nodo identificato da Expression2. Se il nodo in Expression2 ha già uno o più nodi figlio, è necessario utilizzare as first o as last per specificare la posizione in cui si desidera aggiungere il nuovo nodo, ad esempio rispettivamente all'inizio o alla fine dell'elenco di nodi. Le parole chiave as first e as last vengono ignorate se si inseriscono attributi.after
I nodi identificati da Expression1 vengono inseriti come nodi di pari livello immediatamente dopo il nodo identificato da Expression2. Non è possibile utilizzare la parola chiave after per inserire attributi, ad esempio per inserire un costruttore di attributi o per restituire un attributo da una query XQuery.before
I nodi identificati da Expression1 vengono inseriti come nodi di pari livello immediatamente prima del nodo identificato da Expression2. Non è possibile utilizzare la parola chiave before se vengono inseriti attributi, ad esempio per inserire un costruttore di attributi o per restituire un attributo da una query XQuery.Expression2
Identifica un nodo. I nodi identificati in Expression1 vengono inseriti in relazione al nodo identificato da Expression2. Quest'ultima può essere un'espressione XQuery che restituisce un riferimento a un nodo esistente nel documento a cui viene fatto riferimento. Se vengono restituiti più nodi, l'inserimento avrà esito negativo. Se Expression2 restituisce una sequenza vuota, non viene inserito nulla e non vengono restituiti errori. Se Expression2 non è staticamente un singleton, viene restituito un errore statico. Expression2 non può essere un'istruzione di elaborazione, un commento o un attributo. Si noti che Expression2 deve fare riferimento a un nodo esistente nel documento e non a un nodo costruito.
Esempi
A. Inserimento di nodi elemento nel documento
Nell'esempio seguente viene illustrato l'inserimento di elementi in un documento. Innanzitutto viene assegnato un documento XML a una variabile di tipo xml. Viene quindi illustrato l'inserimento di nodi elemento nel documento tramite numerose istruzioni XML DML insert. Dopo ogni inserimento, l'istruzione SELECT visualizza il risultato.
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
Si noti che in diverse espressioni di percorso dell'esempio è specificato "[1]" come requisito per la tipizzazione statica, in modo tale da garantire la presenza di un singolo nodo di destinazione.
B. Inserimento di più elementi nel documento
Nell'esempio seguente un documento viene innanzitutto assegnato a una variabile di tipo xml. Una sequenza di due elementi, che rappresenta le funzionalità del prodotto, viene quindi assegnata a una seconda variabile di tipo xml. Questa sequenza viene quindi inserita nella prima variabile.
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
C. Inserimento di attributi in un documento
Nell'esempio seguente viene illustrato l'inserimento di attributi in un documento. Innanzitutto viene assegnato un documento a una variabile di tipo xml. Viene quindi utilizzata una serie di istruzioni XML DML insert per inserire gli attributi nel documento. Dopo ogni inserimento di un attributo, l'istruzione SELECT visualizza il risultato.
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. Inserimento di un nodo di commento
In questa query viene innanzitutto assegnato un documento XML a una variabile di tipo xml. Viene quindi utilizzato il linguaggio XML DML per inserire un nodo di commento dopo il primo elemento <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. Inserimento di un'istruzione di elaborazione
Nella query seguente, viene innanzitutto assegnato un documento XML a una variabile di tipo xml. Viene quindi utilizzata la parola chiave XML DML per inserire un'istruzione di elaborazione all'inizio del documento.
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. Inserimento di dati tramite una sezione CDATA
Quando si inserisce testo che include caratteri non validi in XML, ad esempio < o >, è possibile utilizzare le sezioni CDATA per inserire i dati come illustrato nella query seguente. Nella query viene specificata una sezione CDATA che tuttavia viene aggiunta come un nodo di testo nel quale i caratteri non validi sono convertiti in entità, ad esempio '<' viene salvato come <.
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
La query inserisce un nodo di testo nell'elemento <Features>:
<Root>
<ProductDescription ProductID="1" ProductName="Road Bike">
<Features> <notxml> as text </notxml> or cdata </Features>
</ProductDescription>
</Root>
G. Inserimento di un nodo di testo
In questa query viene innanzitutto assegnato un documento XML a una variabile di tipo xml. Viene quindi utilizzato il linguaggio XML DML per inserire un nodo di testo come primo figlio dell'elemento <Root>. Per specificare il testo viene utilizzato il costruttore di testo.
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. Inserimento di un nuovo elemento in una colonna xml non tipizzata
Nell'esempio seguente viene utilizzato il linguaggio XML DML per aggiornare un'istanza XML archiviata in una colonna di tipo 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
Anche in questo caso, quando viene inserito il nodo elemento <Material>, l'espressione di percorso deve restituire una singola destinazione. Questo requisito viene specificato in modo esplicito tramite l'aggiunta di [1] alla fine dell'espressione.
-- check the update
SELECT x.query(' //ProductDescription/Features')
FROM T;
GO
I. Inserimento basato su un'istruzione che include la condizione IF
Nell'esempio seguente, una condizione IF viene specificata come parte di Expression1 nell'istruzione XML DML insert. Se la condizione è True, all'elemento <WorkCenter> viene aggiunto un attributo.
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
L'esempio seguente è simile, eccetto che per il fatto che l'istruzione XML DML insert inserisce un elemento nel documento se la condizione è True, ovvero se l'elemento <WorkCenter> include un numero inferiore o uguale a due di elementi figlio <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
Risultato:
<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. Inserimento di nodi in una colonna xml tipizzata
In questo esempio vengono inseriti un elemento e un attributo in un codice XML delle istruzioni di produzione archiviato in una colonna xml tipizzata.
Nell'esempio viene innanzitutto creata nel database AdventureWorks una tabella (T) con una colonna xml tipizzata. Un'istanza del codice XML delle istruzioni di produzione viene quindi copiata dalla colonna Instructions della tabella ProductModel nella tabella T. Gli inserimenti vengono quindi applicati al codice XML nella tabella 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