Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
gäller för:SQL Server
I XQuery kan du använda direkt och beräknade konstruktorer för att konstruera XML-strukturer i en fråga.
Not
Det finns ingen skillnad mellan de direkta och beräknade konstruktorerna.
Använda direktkonstruktorer
När du använder direktkonstruktorer anger du XML-liknande syntax när du skapar XML. Följande exempel illustrerar XML-konstruktion av direktkonstruktorerna.
Skapa element
När du använder XML-noteringar kan du skapa element. I följande exempel används det direkta elementkonstruktoruttrycket och ett <ProductModel> element skapas. Det konstruerade elementet har tre underordnade element
En textnod.
Två elementnoder och
<Summary><Features>.Elementet
<Summary>har en underordnad textnod vars värde är"Some description".Elementet
<Features>har underordnade elementnoder,<Color>,<Weight>och<Warranty>. Var och en av dessa noder har en underordnad textnod och har värdenaRed,25,2 years parts and laborrespektive .
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('<ProductModel ProductModelID="111">;
This is product model catalog description.
<Summary>Some description</Summary>
<Features>
<Color>Red</Color>
<Weight>25</Weight>
<Warranty>2 years parts and labor</Warranty>
</Features></ProductModel>');
Här är den resulterande XML:en:
<ProductModel ProductModelID="111">
This is product model catalog description.
<Summary>Some description</Summary>
<Features>
<Color>Red</Color>
<Weight>25</Weight>
<Warranty>2 years parts and labor</Warranty>
</Features>
</ProductModel>
Även om det är användbart att konstruera element från konstanta uttryck, vilket visas i det här exemplet, är den sanna kraften i den här XQuery-språkfunktionen möjligheten att konstruera XML som dynamiskt extraherar data från en databas. Du kan använda klammerparenteser för att ange frågeuttryck. I den resulterande XML-koden ersätts uttrycket med dess värde. Följande fråga skapar till exempel ett <NewRoot> element med ett underordnat element (<e>). Värdet för elementet <e> beräknas genom att ange ett sökvägsuttryck inuti klammerparenteser ("{ ... }").
DECLARE @x AS XML;
SET @x = '<root>5</root>';
SELECT @x.query('<NewRoot><e> { /root } </e></NewRoot>');
Klammerparenteserna fungerar som kontextväxlingstoken och växlar frågan från XML-konstruktion till frågeutvärdering. I det här fallet utvärderas XQuery-sökvägsuttrycket inuti klammerparenteserna, /root, och resultatet ersätts med det.
Här är resultatet:
<NewRoot>
<e>
<root>5</root>
</e>
</NewRoot>
Följande fråga liknar den föregående. Uttrycket i klammerparenteserna anger data() dock funktionen för att hämta elementets <root> atomiska värde och tilldelar det till det konstruerade elementet , <e>.
DECLARE @x AS XML;
SET @x = '<root>5</root>';
DECLARE @y AS XML;
SET @y = (SELECT @x.query('
<NewRoot>
<e> { data(/root) } </e>
</NewRoot>'));
SELECT @y;
Här är resultatet:
<NewRoot>
<e>5</e>
</NewRoot>
Om du vill använda klammerparenteserna som en del av texten i stället för kontextväxlingstoken kan du undvika dem som "}}" eller "{{", som du ser i det här exemplet:
DECLARE @x AS XML;
SET @x = '<root>5</root>';
DECLARE @y AS XML;
SET @y = (SELECT @x.query('
<NewRoot> Hello, I can use {{ and }} as part of my text</NewRoot>'));
SELECT @y;
Här är resultatet:
<NewRoot> Hello, I can use { and } as part of my text</NewRoot>
Följande fråga är ett annat exempel på hur du skapar element med hjälp av konstruktorn för direktelement. Dessutom hämtas värdet för elementet <FirstLocation> genom att uttrycket körs i klammerparenteserna. Frågeuttrycket returnerar tillverkningsstegen på den första arbetsställeplatsen från kolumnen Instruktioner i tabellen Production.ProductModel.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
<FirstLocation>
{ /AWMI:root/AWMI:Location[1]/AWMI:step }
</FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Här är resultatet:
<FirstLocation>
<AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">
Insert <AWMI:material>aluminum sheet MS-2341</AWMI:material> into the <AWMI:tool>T-85A framing tool</AWMI:tool>.
</AWMI:step>
<AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">
Attach <AWMI:tool>Trim Jig TJ-26</AWMI:tool> to the upper and lower right corners of the aluminum sheet.
</AWMI:step>
...
</FirstLocation>
Elementinnehåll i XML-konstruktion
I följande exempel visas hur uttrycken konstruerar elementinnehåll med hjälp av konstruktorn för direktelement. I följande exempel anger konstruktorn för direktelement ett uttryck. För det här uttrycket skapas en textnod i den resulterande XML-koden.
DECLARE @x AS XML;
SET @x = '
<root>
<step>This is step 1</step>
<step>This is step 2</step>
<step>This is step 3</step>
</root>';
SELECT @x.query('
<result>
{ for $i in /root[1]/step
return string($i)
}
</result>');
Den atomiska värdesekvensen som är resultatet av uttrycksutvärderingen läggs till i textnoden med ett blanksteg som läggs till mellan de intilliggande atomiska värdena, vilket visas i resultatet. Det konstruerade elementet har ett underordnat element. Det här är en textnod som innehåller det värde som visas i resultatet.
<result>This is step 1 This is step 2 This is step 3</result>
I stället för ett uttryck, om du anger tre separata uttryck som genererar tre textnoder, sammanfogas de intilliggande textnoderna till en enda textnod, genom sammanfogning, i den resulterande XML-koden.
DECLARE @x AS XML;
SET @x = '
<root>
<step>This is step 1</step>
<step>This is step 2</step>
<step>This is step 3</step>
</root>';
SELECT @x.query('
<result>
{ string(/root[1]/step[1]) }
{ string(/root[1]/step[2]) }
{ string(/root[1]/step[3]) }
</result>');
Den konstruerade elementnoden har en underordnad. Det här är en textnod som innehåller det värde som visas i resultatet.
<result>This is step 1This is step 2This is step 3</result>
Skapa attribut
När du skapar element med hjälp av konstruktorn för direktelement kan du också ange attribut för elementet med hjälp av XML-liknande syntax, som du ser i det här exemplet:
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('<ProductModel ProductModelID="111">;
This is product model catalog description.
<Summary>Some description</Summary>
</ProductModel>');
Här är den resulterande XML:en:
<ProductModel ProductModelID="111">
This is product model catalog description.
<Summary>Some description</Summary>
</ProductModel>
Det konstruerade elementet <ProductModel> har ett ProductModelID-attribut och dessa underordnade noder:
En textnod
This is product model catalog description.En elementnod,
<Summary>. Den här noden har en underordnad textnod,Some description.
När du skapar ett attribut kan du ange dess värde med ett uttryck i klammerparenteser. I det här fallet returneras resultatet av uttrycket som attributvärde.
I följande exempel data() är funktionen inte strikt obligatorisk. Eftersom du tilldelar uttrycksvärdet till ett attribut data() tillämpas implicit för att hämta det typgivna värdet för det angivna uttrycket.
DECLARE @x AS XML;
SET @x = '<root>5</root>';
DECLARE @y AS XML;
SET @y = (SELECT @x.query('<NewRoot attr="{ data(/root) }" ></NewRoot>'));
SELECT @y;
Här är resultatet:
<NewRoot attr="5" />
Följande är ett annat exempel där uttryck anges för attributkonstruktionen LocationID och SetupHrs. Dessa uttryck utvärderas mot XML i kolumnen Instruktion. Uttryckets typerade värde tilldelas attributen.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
<FirstLocation
LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
{ /AWMI:root/AWMI:Location[1]/AWMI:step }
</FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Här är det partiella resultatet:
<FirstLocation LocationID="10" SetupHours="0.5" >
<AWMI:step ...
</AWMI:step>
...
</FirstLocation>
Implementeringsbegränsningar
Det här är begränsningarna:
Flera eller blandade attribututtryck (sträng- och XQuery-uttryck) stöds inte. Som du till exempel ser i följande fråga skapar du XML där
Itemär en konstant och värdet5hämtas genom att utvärdera ett frågeuttryck:<a attr="Item 5" />Följande fråga returnerar ett fel eftersom du blandar konstant sträng med ett uttryck ({/x}) och detta stöds inte:
DECLARE @x AS XML; SET @x = '<x>5</x>'; SELECT @x.query('<a attr="Item {/x}"/>');I det här fallet har du följande alternativ:
Skapa attributvärdet genom sammanfogning av två atomiska värden. Dessa atomiska värden serialiseras till attributvärdet med ett blanksteg mellan atomvärdena:
SELECT @x.query('<a attr="{''Item'', data(/x)}"/>');Här är resultatet:
<a attr="Item 5" />Använd funktionen concat för att sammanfoga de två strängargumenten till det resulterande attributvärdet:
SELECT @x.query('<a attr="{concat(''Item'', /x[1])}"/>');I det här fallet läggs inget utrymme till mellan de två strängvärdena. Om du vill ha ett blanksteg mellan de två värdena måste du uttryckligen ange det.
Här är resultatet:
<a attr="Item5" />
Flera uttryck som ett attributvärde stöds inte. Följande fråga returnerar till exempel ett fel:
DECLARE @x AS XML; SET @x = '<x>5</x>'; SELECT @x.query('<a attr="{/x}{/x}"/>');Heterogena sekvenser stöds inte. Alla försök att tilldela en heterogen sekvens som ett attributvärde returnerar ett fel, enligt följande exempel. I det här exemplet anges en heterogen sekvens, en sträng "Item" och ett element
<x>som attributvärde:DECLARE @x AS XML; SET @x = '<x>5</x>'; SELECT @x.query('<a attr="{''Item'', /x }" />');Om du använder
data()funktionen fungerar frågan eftersom den hämtar det atomiska värdet för uttrycket ,/xsom sammanfogas med strängen. Följande är en sekvens med atomiska värden:SELECT @x.query('<a attr="{''Item'', data(/x)}"/>');Här är resultatet:
<a attr="Item 5" />Attributnodordningen framtvingas under serialiseringen i stället för vid kontroll av statisk typ. Följande fråga misslyckas till exempel eftersom den försöker lägga till ett attribut efter en nod utan attribut.
SELECT CONVERT (XML, '').query(' element x { attribute att { "pass" }, element y { "Element text" }, attribute att2 { "fail" } } '); GOFöregående fråga returnerar följande fel:
XML well-formedness check: Attribute cannot appear outside of element declaration. Rewrite your XQuery so it returns well-formed XML.
Lägga till namnområden
När du skapar XML med hjälp av direktkonstruktorerna kan de konstruerade element- och attributnamnen kvalificeras med hjälp av ett namnområdesprefix. Du kan binda prefixet till namnområdet på följande sätt:
- Genom att använda ett namnområdesdeklarationsattribut.
- Genom att
WITH XMLNAMESPACESanvända -satsen. - I XQuery-prologen.
Använda ett namnområdesdeklarationsattribut för att lägga till namnområden
I följande exempel används ett namnområdesdeklarationsattribut i konstruktionen av elementet <a> för att deklarera ett standardnamnområde. Konstruktionen av det underordnade elementet <b> ångrar deklarationen för standardnamnområdet som deklarerats i det överordnade elementet.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
<a xmlns="a">
<b xmlns=""/>
</a>');
Här är resultatet:
<a xmlns="a">
<b xmlns="" />
</a>
Du kan tilldela ett prefix till namnområdet. Prefixet anges i konstruktionen av elementet <a>.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
<x:a xmlns:x="a">
<b/>
</x:a>');
Här är resultatet:
<x:a xmlns:x="a">
<b />
</x:a>
Du kan avregistrera ett standardnamnområde i XML-konstruktionen, men du kan inte avregistrera ett namnområdesprefix. Följande fråga returnerar ett fel eftersom du inte kan av deklarera ett prefix enligt beskrivningen i konstruktionen av elementet <b>.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
<x:a xmlns:x="a">
<b xmlns:x=""/>
</x:a>');
Det nyligen skapade namnområdet är tillgängligt att använda i frågan. Följande fråga deklarerar till exempel ett namnområde när elementet skapas, <FirstLocation>, och anger prefixet i uttrycken för attributvärdena LocationID och SetupHrs.
SELECT Instructions.query('
<FirstLocation xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
{ /AWMI:root/AWMI:Location[1]/AWMI:step }
</FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Om du skapar ett nytt namnområdesprefix på det här sättet åsidosätts alla befintliga namnområdesdeklarationer för det här prefixet. Till exempel åsidosättas namnområdesdeklarationen , AWMI="https://someURI"i frågeprologen av namnområdesdeklarationen i elementet <FirstLocation> .
SELECT Instructions.query('
declare namespace AWMI="https://someURI";
<FirstLocation xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
{ /AWMI:root/AWMI:Location[1]/AWMI:step }
</FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Använd en prolog för att lägga till namnområden
Det här exemplet illustrerar hur namnområden kan läggas till i den konstruerade XML-koden. Ett standardnamnområde deklareras i frågeprologen.
DECLARE @x AS XML;
SET @x = '<x>5</x>';
SELECT @x.query('
declare default element namespace "a";
<a><b xmlns=""/></a>');
I konstruktionen av elementet <b>anges attributet för namnområdesdeklaration med en tom sträng som värde. Detta av deklarerar standardnamnområdet som deklareras i det överordnade objektet.
Här är resultatet:
<a xmlns="a">
<b xmlns="" />
</a>
XML-konstruktion och hantering av tomt utrymme
Elementinnehållet i XML-konstruktionen kan innehålla blankstegstecken. Dessa tecken hanteras på följande sätt:
Blankstegstecken i namnområdes-URI:er behandlas som XSD-typen
anyURI. Mer specifikt är det så här de hanteras:- Eventuella blankstegstecken i början och slutet trimmas.
- Interna blankstegsteckenvärden komprimeras till ett enda blanksteg
Radmatningstecken i attributinnehållet ersätts av blanksteg. Alla andra blankstegstecken finns kvar som de är.
Det tomma utrymmet inuti element bevaras.
I följande exempel visas hantering av blanksteg i XML-konstruktion:
-- line feed is replaced by space.
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('
declare namespace myNS=" https://
abc/
xyz
";
<test attr=" my
test attr
value " >
<a>
This is a
test
</a>
</test>
') AS XML_Result;
Här är resultatet:
-- result
<test attr="<test attr=" my test attr value "><a>
This is a
test
</a></test>
"><a>
This is a
test
</a></test>
Andra direkta XML-konstruktorer
Konstruktorerna för bearbetning av instruktioner och XML-kommentarer använder samma syntax som motsvarande XML-konstruktionssyntax. Beräknade konstruktorer för textnoder stöds också, men används främst i XML DML för att konstruera textnoder.
Not
Ett exempel på hur du använder en explicit textnodkonstruktor finns i det specifika exemplet i Insert (XML DML).
I följande fråga innehåller den konstruerade XML-koden ett element, två attribut, en kommentar och en bearbetningsinstruktion. Ett kommatecken används före <FirstLocation>, eftersom en sekvens skapas.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
<?myProcessingInstr abc="value" ?>,
<FirstLocation
WorkCtrID = "{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
<!-- some comment -->
<?myPI some processing instructions ?>
{ (/AWMI:root/AWMI:Location[1]/AWMI:step) }
</FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Här är det partiella resultatet:
<?myProcessingInstr abc="value" ?>
<FirstLocation WorkCtrID="10" SetupHrs="0.5">
<!-- some comment -->
<?myPI some processing instructions ?>
<AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">I
nsert <AWMI:material>aluminum sheet MS-2341</AWMI:material> into the <AWMI:tool>T-85A framing tool</AWMI:tool>.
</AWMI:step>
...
</FirstLocation>
Använda beräknade konstruktorer
I det här fallet anger du de nyckelord som identifierar vilken typ av nod du vill skapa. Endast följande nyckelord stöds:
- element
- attribut
- SMS
För element- och attributnoder följs dessa nyckelord av nodnamn och även av uttrycket, omgivet av klammerparenteser, som genererar innehållet för noden. I följande exempel skapar du den här XML:en:
<root>
<ProductModel PID="5">Some text <summary>Some Summary</summary></ProductModel>
</root>
Här är frågan som använder beräknade konstruktorer genererar XML:
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('element root
{
element ProductModel
{
attribute PID { 5 },
text{"Some text "},
element summary { "Some Summary" }
}
} ');
Uttrycket som genererar nodinnehållet kan ange ett frågeuttryck.
DECLARE @x AS XML;
SET @x = '<a attr="5"><b>some summary</b></a>';
SELECT @x.query('element root
{
element ProductModel
{
attribute PID { /a/@attr },
text{"Some text "},
element summary { /a/b }
}
} ');
Med det beräknade elementet och attributkonstruktorerna, enligt definitionen i XQuery-specifikationen, kan du beräkna nodnamnen. När du använder direktkonstruktorer i SQL Server måste nodnamnen, till exempel element och attribut, anges som konstanta literaler. Därför finns det ingen skillnad i direkta konstruktorer och beräknade konstruktorer för element och attribut.
I följande exempel hämtas innehållet för de konstruerade noderna från XML-tillverkningsinstruktionerna som lagras i kolumnen Instruktioner i xml- datatyp i tabellen ProductModel.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
element FirstLocation
{
attribute LocationID { (/AWMI:root/AWMI:Location[1]/@LocationID)[1] },
element AllTheSteps { /AWMI:root/AWMI:Location[1]/AWMI:step }
}
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Här är det partiella resultatet:
<FirstLocation LocationID="10">
<AllTheSteps>
<AWMI:step> ... </AWMI:step>
<AWMI:step> ... </AWMI:step>
...
</AllTheSteps>
</FirstLocation>
Andra implementeringsbegränsningar
Konstruktorer för beräknade attribut kan inte användas för att deklarera ett nytt namnområde. Dessutom stöds inte följande beräknade konstruktorer i SQL Server:
- Konstruktorer för beräknade dokumentnoder
- Instruktionskonstruktorer för beräknad bearbetning
- Beräknade kommentarskonstruktorer