Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of mappen te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen om mappen te wijzigen.
Van toepassing op:SQL Server
XQuery definieert de syntaxis van de FLWOR-iteratie. FLWOR is het acroniem voor , , , en forlet. whereorder byreturn
Een FLWOR-verklaring bestaat uit de volgende onderdelen:
Een of meer componenten waarmee een of meer
FORiteratorvariabelen aan invoerreeksen worden gekoppeld.Invoerreeksen kunnen andere XQuery-expressies zijn, zoals XPath-expressies. Dit zijn reeksen knooppunten of reeksen atomische waarden. Atomische waardereeksen kunnen worden samengesteld met behulp van letterlijke waarden of constructorfuncties. Samengestelde XML-knooppunten zijn niet toegestaan als invoerreeksen in SQL Server.
Een optionele
letclausule. Met deze component wordt een waarde toegewezen aan de opgegeven variabele voor een specifieke iteratie. De toegewezen expressie kan een XQuery-expressie zijn, zoals een XPath-expressie, en kan een reeks knooppunten of een reeks atomische waarden retourneren. Atomische waardereeksen kunnen worden samengesteld met behulp van letterlijke waarden of constructorfuncties. Samengestelde XML-knooppunten zijn niet toegestaan als invoerreeksen in SQL Server.Een iteratorvariabele. Deze variabele kan een optionele typeverklaring hebben met behulp van het
astrefwoord.Een optionele
whereclausule. Met deze component wordt een filterpredicaat toegepast op de iteratie.Een optionele
order byclausule.Een
returnexpressie. Met de expressie in dereturncomponent wordt het resultaat van de FLWOR-instructie samengesteld.
De volgende query doorloopt bijvoorbeeld de elementen op de <Step> eerste productielocatie en retourneert de tekenreekswaarde van de <Step> knooppunten:
DECLARE @x AS XML;
SET @x = '<ManuInstructions ProductModelID="1" ProductModelName="SomeBike" >
<Location LocationID="L1" >
<Step>Manu step 1 at Loc 1</Step>
<Step>Manu step 2 at Loc 1</Step>
<Step>Manu step 3 at Loc 1</Step>
</Location>
<Location LocationID="L2" >
<Step>Manu step 1 at Loc 2</Step>
<Step>Manu step 2 at Loc 2</Step>
<Step>Manu step 3 at Loc 2</Step>
</Location>
</ManuInstructions>';
SELECT @x.query('
for $step in /ManuInstructions/Location[1]/Step
return string($step)
');
Dit is het resultaat:
Manu step 1 at Loc 1 Manu step 2 at Loc 1 Manu step 3 at Loc 1
De volgende query is vergelijkbaar met de vorige, behalve dat deze is opgegeven in de kolom Instructies, een getypte XML-kolom, van de tabel ProductModel. De query doorloopt alle productiestappen, <step> elementen, op de eerste locatie van het werkcentrum voor een specifiek product.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
for $Step in //AWMI:root/AWMI:Location[1]/AWMI:step
return
string($Step)
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Let op het volgende uit de vorige query:
Dit
$Stepis de iteratorvariabele.Met de padexpressie wordt
//AWMI:root/AWMI:Location[1]/AWMI:stepde invoerreeks gegenereerd. Deze reeks is de volgorde van de onderliggende elementen van het <step> eerste <Location> elementknooppunt.De optionele predicaatcomponent,
wherewordt niet gebruikt.De
returnexpressie retourneert een tekenreekswaarde van het <step> element.
De tekenreeksfunctie (XQuery) wordt gebruikt om de tekenreekswaarde van het <step> knooppunt op te halen.
Dit is het gedeeltelijke resultaat:
Insert aluminum sheet MS-2341 into the T-85A framing tool.
Attach Trim Jig TJ-26 to the upper and lower right corners of
the aluminum sheet. ....
Dit zijn voorbeelden van andere invoerreeksen die zijn toegestaan:
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('
for $a in (1, 2, 3)
return $a');
-- result = 1 2 3
DECLARE @x AS XML;
SET @x = '';
SELECT @x.query('
for $a in
for $b in (1, 2, 3)
return $b
return $a');
-- result = 1 2 3
DECLARE @x AS XML;
SET @x = '<ROOT><a>111</a></ROOT>';
SELECT @x.query('
for $a in (xs:string( "test"), xs:double( "12" ), data(/ROOT/a ))
return $a');
-- result test 12 111
In SQL Server zijn heterogene reeksen niet toegestaan. Sequenties die een combinatie van atomische waarden en knooppunten bevatten, zijn niet toegestaan.
Iteratie wordt vaak samen met de XQuery-syntaxis (XML-constructie) gebruikt voor het transformeren van XML-indelingen, zoals wordt weergegeven in de volgende query.
In de voorbeelddatabase AdventureWorks hebben de productie-instructies die zijn opgeslagen in de Instructions kolom van de Production.ProductModel tabel de volgende vorm:
<Location LocationID="10" LaborHours="1.2"
SetupHours=".2" MachineHours=".1">
<step>describes 1st manu step</step>
<step>describes 2nd manu step</step>
...
</Location>
...
Met de volgende query wordt een nieuwe XML samengesteld die de <Location> elementen bevat met de locatiekenmerken van het werkcentrum die als onderliggende elementen worden geretourneerd:
<Location>
<LocationID>10</LocationID>
<LaborHours>1.2</LaborHours>
<SetupHours>.2</SetupHours>
<MachineHours>.1</MachineHours>
</Location>
...
Dit is de query:
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
for $WC in /AWMI:root/AWMI:Location
return
<Location>
<LocationID> { data($WC/@LocationID) } </LocationID>
<LaborHours> { data($WC/@LaborHours) } </LaborHours>
<SetupHours> { data($WC/@SetupHours) } </SetupHours>
<MachineHours> { data($WC/@MachineHours) } </MachineHours>
</Location>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Let op de volgende overwegingen uit de vorige query:
De FLWOR-instructie haalt een reeks <
Location> elementen voor een specifiek product op.De gegevensfunctie (XQuery) wordt gebruikt om de waarde van elk kenmerk te extraheren, zodat ze worden toegevoegd aan de resulterende XML als tekstknooppunten in plaats van als kenmerken.
Met de expressie in de
RETURNcomponent wordt de gewenste XML samengesteld.
Dit is een gedeeltelijk resultaat:
<Location>
<LocationID>10</LocationID>
<LaborHours>2.5</LaborHours>
<SetupHours>0.5</SetupHours>
<MachineHours>3</MachineHours>
</Location>
<Location>
...
<Location>
...
let De component gebruiken
U kunt de let component gebruiken om herhalende expressies te noemen waarnaar u kunt verwijzen door te verwijzen naar de variabele. De expressie die aan een let variabele is toegewezen, wordt telkens in de query ingevoegd wanneer naar de variabele wordt verwezen in de query. Dit betekent dat de instructie zo vaak wordt uitgevoerd als er naar de expressie wordt verwezen.
In de AdventureWorks2025 database bevatten de productie-instructies informatie over de vereiste hulpprogramma's en de locatie waar de hulpprogramma's worden gebruikt. De volgende query maakt gebruik van de let component om de hulpprogramma's weer te geven die nodig zijn voor het bouwen van een productiemodel en de locaties waar elk hulpprogramma nodig is.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
for $T in //AWMI:tool
let $L := //AWMI:Location[.//AWMI:tool[.=data($T)]]
return
<tool desc="{data($T)}" Locations="{data($L/@LocationID)}"/>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
where De component gebruiken
U kunt de where component gebruiken om de resultaten van een iteratie te filteren. Dit wordt geïllustreerd in dit volgende voorbeeld.
In de productie van een fiets doorloopt het productieproces een reeks werkcentrumlocaties. Elke locatie van het werkcentrum definieert een reeks productiestappen. Met de volgende query worden alleen de werkcentrumlocaties opgehaald die een fietsmodel produceren en minder dan drie productiestappen hebben. Dat wil gezegd hebben ze minder dan drie <step> elementen.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
for $WC in /AWMI:root/AWMI:Location
where count($WC/AWMI:step) < 3
return
<Location >
{ $WC/@LocationID }
</Location>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Let op het volgende in de vorige query:
Het
wheretrefwoord gebruikt decount()functie om het aantal <step> onderliggende elementen op elke locatie van het werkcentrum te tellen.Met
returnde expressie wordt de GEWENSTE XML samengesteld uit de resultaten van de iteratie.
Dit is het resultaat:
<Location LocationID="30"/>
Het resultaat van de expressie in de where component wordt geconverteerd naar een Booleaanse waarde met behulp van de volgende regels, in de opgegeven volgorde. Dit zijn dezelfde regels voor predicaten in padexpressies, behalve dat gehele getallen niet zijn toegestaan:
Als de
whereexpressie een lege reeks retourneert, is de effectieve Booleaanse waarde Onwaar.Als de
whereexpressie één eenvoudige Booleaanse waarde retourneert, is deze waarde de effectieve Booleaanse waarde.Als de
whereexpressie een reeks retourneert die ten minste één knooppunt bevat, is de effectieve Booleaanse waarde Waar.Anders wordt er een statische fout gegenereerd.
Meerdere variabele binding in FLWOR
U kunt één FLWOR-expressie hebben waarmee meerdere variabelen aan invoerreeksen worden gekoppeld. In het volgende voorbeeld wordt de query opgegeven voor een niet-getypte XML-variabele. De FLOWR-expressie retourneert het eerste <Step> element onderliggend element in elk <Location> element.
DECLARE @x AS XML;
SET @x = '<ManuInstructions ProductModelID="1" ProductModelName="SomeBike" >
<Location LocationID="L1" >
<Step>Manu step 1 at Loc 1</Step>
<Step>Manu step 2 at Loc 1</Step>
<Step>Manu step 3 at Loc 1</Step>
</Location>
<Location LocationID="L2" >
<Step>Manu step 1 at Loc 2</Step>
<Step>Manu step 2 at Loc 2</Step>
<Step>Manu step 3 at Loc 2</Step>
</Location>
</ManuInstructions>';
SELECT @x.query('
for $Loc in /ManuInstructions/Location,
$FirstStep in $Loc/Step[1]
return
string($FirstStep)
');
Let op het volgende uit de vorige query:
De
forexpressie definieert$Locen $FirstStepvariabelen.De
twoexpressies en/ManuInstructions/Location$FirstStep in $Loc/Step[1], worden gecorreleerd in dat de waarden van afhankelijk zijn van$FirstStepde waarden van$Loc.De expressie die is gekoppeld aan
$Lochet genereren van <Location> een reeks elementen. Voor elk <Location> element$FirstStepgenereert u een reeks van één <Step> element, een singleton.$Locis opgegeven in de expressie die is gekoppeld aan de$FirstStepvariabele.
Dit is het resultaat:
Manu step 1 at Loc 1
Manu step 1 at Loc 2
De volgende query is vergelijkbaar, behalve dat deze is opgegeven voor de kolom Instructies, de getypte XML-kolom van de ProductModel tabel.
XML-constructie (XQuery) wordt gebruikt om de gewenste XML te genereren.
SELECT Instructions.query('
declare default element namespace "https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
for $WC in /root/Location,
$S in $WC/step
return
<Step LocationID= "{$WC/@LocationID }" >
{ $S/node() }
</Step>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Let op het volgende in de vorige query:
De
forcomponent definieert twee variabelen en$WC$S. De expressie die is gekoppeld aan$WCgenereert een reeks werkcentrumlocaties in de productie van een fietsproductmodel. De padexpressie die aan de$Svariabele is toegewezen, genereert een reeks stappen voor elke locatiereeks van het werkcentrum in de$WC.De retourinstructie bouwt XML met een <
Step> element dat de productiestap en hetLocationIDkenmerk bevat.De declareer standaardelementnaamruimte wordt gebruikt in het XQuery-prolog, zodat alle naamruimtedeclaraties in de resulterende XML worden weergegeven op het element op het hoogste niveau. Hierdoor is het resultaat beter leesbaar. Zie Naamruimten verwerken in XQuery voor meer informatie over standaardnaamruimten.
Dit is het gedeeltelijke resultaat:
<Step xmlns=
"https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
LocationID="10">
Insert <material>aluminum sheet MS-2341</material> into the <tool>T-
85A framing tool</tool>.
</Step>
...
<Step xmlns=
"https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
LocationID="20">
Assemble all frame components following blueprint
<blueprint>1299</blueprint>.
</Step>
...
order by De component gebruiken
Sorteren in XQuery wordt uitgevoerd met behulp van de order by component in de FLWOR-expressie. De sorteerexpressies die aan de order by component worden doorgegeven, moeten waarden retourneren waarvan de typen geldig zijn voor de gt operator. Elke sorteerexpressie moet resulteren in een singleton van een reeks met één item. Standaard wordt sorteren uitgevoerd in oplopende volgorde. U kunt desgewenst een oplopende of aflopende volgorde opgeven voor elke sorteerexpressie.
Opmerking
Het sorteren van vergelijkingen op tekenreekswaarden die door de XQuery-implementatie in SQL Server worden uitgevoerd, worden altijd uitgevoerd met behulp van de binaire Unicode-codepuntsortering.
Met de volgende query worden alle telefoonnummers voor een specifieke klant opgehaald uit de kolom AdditionalContactInfo. De resultaten worden gesorteerd op telefoonnummer.
USE AdventureWorks2022;
GO
SELECT AdditionalContactInfo.query('
declare namespace act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes";
declare namespace aci="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo";
for $a in /aci:AdditionalContactInfo//act:telephoneNumber
order by $a/act:number[1] descending
return $a
') AS Result
FROM Person.Person
WHERE BusinessEntityID = 291;
Het atomenisatieproces (XQuery) haalt de atomische waarde van de <number> elementen op voordat het wordt doorgegeven aan order by. U kunt de expressie schrijven met behulp van de data() functie, maar dat is niet vereist.
order by data($a/act:number[1]) descending
Dit is het resultaat:
<act:telephoneNumber xmlns:act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">
<act:number>333-333-3334</act:number>
</act:telephoneNumber>
<act:telephoneNumber xmlns:act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">
<act:number>333-333-3333</act:number>
</act:telephoneNumber>
In plaats van de naamruimten in het queryprolog te declareren, kunt u ze declareren met behulp van WITH XMLNAMESPACES.
WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes' AS act, 'https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo' AS aci)
SELECT AdditionalContactInfo.query('
for $a in /aci:AdditionalContactInfo//act:telephoneNumber
order by $a/act:number[1] descending
return $a
') AS Result
FROM Person.Person
WHERE BusinessEntityID = 291;
U kunt ook sorteren op kenmerkwaarde. Met de volgende query worden bijvoorbeeld de zojuist gemaakte <Location> elementen opgehaald met de kenmerken LocationID en LaborHours, gesorteerd op het kenmerk LaborHours in aflopende volgorde. Als gevolg hiervan worden de werkcentrumlocaties met de maximale arbeidsuren eerst geretourneerd.
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
for $WC in /AWMI:root/AWMI:Location
order by $WC/@LaborHours descending
return
<Location>
{ $WC/@LocationID }
{ $WC/@LaborHours }
</Location>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;
Dit is het resultaat:
<Location LocationID="60" LaborHours="4"/>
<Location LocationID="50" LaborHours="3"/>
<Location LocationID="10" LaborHours="2.5"/>
<Location LocationID="20" LaborHours="1.75"/>
<Location LocationID="30" LaborHours="1"/>
<Location LocationID="45" LaborHours=".5"/>
In de volgende query worden de resultaten gesorteerd op elementnaam. De query haalt de specificaties van een specifiek product op uit de productcatalogus. De specificaties zijn de onderliggende elementen van het <Specifications> element.
SELECT CatalogDescription.query('
declare namespace
pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
for $a in /pd:ProductDescription/pd:Specifications/*
order by local-name($a)
return $a
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 19;
Let op het volgende uit de vorige query:
De
/p1:ProductDescription/p1:Specifications/*expressie retourneert onderliggende elementen van<Specifications> .De
order by (local-name($a))expressie sorteert de reeks op het lokale deel van de elementnaam.
Dit is het resultaat:
<Color>Available in most colors</Color>
<Material>Aluminum Alloy</Material>
<ProductLine>Mountain bike</ProductLine>
<RiderExperience>Advanced to Professional riders</RiderExperience>
<Style>Unisex</Style>
Knooppunten waarin de volgorde-expressie leeg retourneert, worden gesorteerd op het begin van de reeks, zoals wordt weergegeven in het volgende voorbeeld:
DECLARE @x AS XML;
SET @x = '<root>
<Person Name="A" />
<Person />
<Person Name="B" />
</root>
';
SELECT @x.query('
for $person in //Person
order by $person/@Name
return $person
');
Dit is het resultaat:
<Person />
<Person Name="A" />
<Person Name="B" />
U kunt meerdere sorteercriteria opgeven, zoals wordt weergegeven in het volgende voorbeeld. De query in dit voorbeeld sorteert <Employee> eerst elementen op Titel en vervolgens op kenmerkwaarden van de beheerder.
DECLARE @x AS XML;
SET @x = '<root>
<Employee ID="10" Title="Teacher" Gender="M" />
<Employee ID="15" Title="Teacher" Gender="F" />
<Employee ID="5" Title="Teacher" Gender="M" />
<Employee ID="11" Title="Teacher" Gender="F" />
<Employee ID="8" Title="Administrator" Gender="M" />
<Employee ID="4" Title="Administrator" Gender="F" />
<Employee ID="3" Title="Teacher" Gender="F" />
<Employee ID="125" Title="Administrator" Gender="F" /></root>';
SELECT @x.query('for $e in /root/Employee
order by $e/@Title ascending, $e/@Gender descending
return
$e
');
Dit is het resultaat:
<Employee ID="8" Title="Administrator" Gender="M" />
<Employee ID="4" Title="Administrator" Gender="F" />
<Employee ID="125" Title="Administrator" Gender="F" />
<Employee ID="10" Title="Teacher" Gender="M" />
<Employee ID="5" Title="Teacher" Gender="M" />
<Employee ID="11" Title="Teacher" Gender="F" />
<Employee ID="15" Title="Teacher" Gender="F" />
<Employee ID="3" Title="Teacher" Gender="F" />
Beperkingen
Dit zijn de beperkingen:
De sorteerexpressies moeten homogeen worden getypt. Dit is statisch gecontroleerd.
Het sorteren van lege reeksen kan niet worden beheerd.
De leegste, lege grootste en sorteringstrefwoorden
order byworden niet ondersteund