Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
platí pro:SQL Server
XQuery definuje syntaxi iterace FLWOR. FLWOR je zkratka pro for, let, where, order bya return.
Prohlášení FLWOR se skládá z následujících částí:
Jedna nebo více
FORklauzulí, které sváže jednu nebo více proměnných iterátoru se vstupními sekvencemi.Vstupní sekvence můžou být jiné výrazy XQuery, jako jsou výrazy XPath. Jedná se o sekvence uzlů nebo posloupnosti atomických hodnot. Sekvence atomických hodnot lze vytvořit pomocí literálů nebo funkcí konstruktoru. Vytvořené uzly XML nejsou povolené jako vstupní sekvence na SQL Serveru.
Volitelná klauzule
let. Tato klauzule přiřadí danou proměnnou hodnotu pro konkrétní iteraci. Přiřazený výraz může být výraz XQuery, například výraz XPath, a může vracet posloupnost uzlů nebo posloupnost atomických hodnot. Sekvence atomických hodnot lze vytvořit pomocí literálů nebo funkcí konstruktoru. Vytvořené uzly XML nejsou povolené jako vstupní sekvence na SQL Serveru.Proměnná iterátoru. Tato proměnná může mít volitelný kontrolní výraz typu pomocí klíčového slova
as.Volitelná klauzule
where. Tato klauzule aplikuje predikát filtru na iteraci.Volitelná klauzule
order by.Výraz
return. Výraz v klauzulireturnvytvoří výsledek příkazu FLWOR.
Například následující dotaz iteruje prvky <Step> v prvním výrobním umístění a vrátí řetězcovou hodnotu <Step> uzlů:
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)
');
Tady je výsledek:
Manu step 1 at Loc 1 Manu step 2 at Loc 1 Manu step 3 at Loc 1
Následující dotaz je podobný předchozímu dotazu, s tím rozdílem, že je zadaný ve sloupci Pokyny, zadaný sloupec XML v tabulce ProductModel. Dotaz iteruje všechny výrobní kroky, <step> prvky, v prvním umístění pracovního centra pro konkrétní produkt.
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;
Všimněte si následujících věcí z předchozího dotazu:
$Stepje proměnná iterátoru.Výraz cesty ,
//AWMI:root/AWMI:Location[1]/AWMI:step, vygeneruje vstupní sekvenci. Tato sekvence je posloupnost podřízeného uzlu elementu <step> prvního uzlu elementu <Location>.Nepovinná predikátová klauzule ,
wherese nepoužívá.Výraz
returnvrátí řetězcovou hodnotu z elementu <step>.
řetězcové funkce (XQuery) se používá k načtení řetězcové hodnoty uzlu <step>.
Tady je částečný výsledek:
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. ....
Tady jsou příklady dalších vstupních sekvencí, které jsou povolené:
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
V SQL Serveru nejsou heterogenní sekvence povolené. Konkrétně nejsou povoleny sekvence, které obsahují kombinaci atomických hodnot a uzlů.
Iterace se často používá společně se syntaxí výstavby XML (XQuery) v transformování formátů XML, jak je znázorněno v dalším dotazu.
V ukázkové databázi AdventureWorks mají výrobní pokyny uložené ve Instructions sloupci Production.ProductModel tabulky následující formulář:
<Location LocationID="10" LaborHours="1.2"
SetupHours=".2" MachineHours=".1">
<step>describes 1st manu step</step>
<step>describes 2nd manu step</step>
...
</Location>
...
Následující dotaz vytvoří nový xml, který má <Location> elementy s atributy umístění pracovního centra vrácenými jako podřízené prvky:
<Location>
<LocationID>10</LocationID>
<LaborHours>1.2</LaborHours>
<SetupHours>.2</SetupHours>
<MachineHours>.1</MachineHours>
</Location>
...
Tady je dotaz:
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;
Všimněte si následujících aspektů z předchozího dotazu:
Příkaz FLWOR načte posloupnost <
Location> prvků pro konkrétní produkt.Datová funkce (XQuery) slouží k extrahování hodnoty každého atributu, takže se přidají do výsledného XML jako textové uzly místo atributů.
Výraz v
RETURNklauzuli vytvoří požadovaný kód XML.
Jedná se o částečný výsledek:
<Location>
<LocationID>10</LocationID>
<LaborHours>2.5</LaborHours>
<SetupHours>0.5</SetupHours>
<MachineHours>3</MachineHours>
</Location>
<Location>
...
<Location>
...
Použití klauzule let
Klauzuli let můžete použít k pojmenování opakujících se výrazů, na které můžete odkazovat odkazováním na proměnnou. Výraz přiřazený proměnné let se vloží do dotazu při každém odkazování na proměnnou v dotazu. To znamená, že příkaz se spustí tolikrát, kolikrát se na výraz odkazuje.
V AdventureWorks2025 databázi obsahují pokyny pro výrobu informace o požadovaných nástrojích a umístění, kde se nástroje používají. Následující dotaz pomocí let klauzule vypíše nástroje potřebné k sestavení produkčního modelu a umístění, kde je každý nástroj potřebný.
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;
Použití klauzule where
Pomocí klauzule where můžete filtrovat výsledky iterace. To je znázorněno v tomto dalším příkladu.
Při výrobě jízdních kol prochází výrobní proces řadou pracovních center. Každé umístění pracovního centra definuje posloupnost výrobních kroků. Následující dotaz načte pouze umístění pracovních center, která vyrábí model jízdních kol a mají méně než tři výrobní kroky. To znamená, že mají méně než tři prvky <step>.
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;
Všimněte si následující položky v předchozím dotazu:
Klíčové
whereslovo používácount()funkci ke spočítání počtu podřízených <step> prvků v každém umístění pracovního centra.Výraz
returnvytvoří požadovaný kód XML z výsledků iterace.
Tady je výsledek:
<Location LocationID="30"/>
Výsledek výrazu v klauzuli where se převede na logickou hodnotu pomocí následujících pravidel v uvedeném pořadí. Jsou stejné jako pravidla pro predikáty ve výrazech cesty s tím rozdílem, že celá čísla nejsou povolená:
Pokud výraz
wherevrátí prázdnou sekvenci, jeho efektivní logická hodnota je False.Pokud výraz
wherevrátí jednu jednoduchou logickou hodnotu typu, jedná se o efektivní logickou hodnotu.Pokud výraz
wherevrátí sekvenci, která obsahuje alespoň jeden uzel, efektivní logická hodnota je True.V opačném případě vyvolá statickou chybu.
Více proměnných vazeb v FLWOR
Můžete mít jeden výraz FLWOR, který vytvoří vazbu více proměnných na vstupní sekvence. V následujícím příkladu je dotaz určen pro netypovou proměnnou XML. Výraz FLOWR vrátí první podřízený prvek <Step> v každém prvku <Location>.
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)
');
Všimněte si následujících věcí z předchozího dotazu:
Výraz
fordefinuje proměnné$Loca $FirstStep.Výrazy
two,/ManuInstructions/Locationa$FirstStep in $Loc/Step[1]korelují v tom, že hodnoty$FirstStepzávisejí na hodnotách$Loc.Výraz přidružený k
$Locvygeneruje sekvenci prvků <Location>. Pro každý prvek <Location>$FirstStepvygeneruje posloupnost jednoho <Step> elementu singleton.$Locje zadán ve výrazu přidruženém k proměnné$FirstStep.
Tady je výsledek:
Manu step 1 at Loc 1
Manu step 1 at Loc 2
Následující dotaz je podobný s tím rozdílem, že je zadaný ve sloupci Pokyny, ve sloupci Xml zadaném v ProductModel tabulce.
Konstrukce XML (XQuery) se používá k vygenerování požadovaného XML.
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;
Všimněte si následující položky v předchozím dotazu:
Klauzule
fordefinuje dvě proměnné,$WCa$S. Výraz přidružený k$WCvygeneruje sekvenci umístění pracovních center při výrobě modelu výrobku jízdních kol. Výraz cesty přiřazený proměnné$Sgeneruje posloupnost kroků pro každou sekvenci umístění pracovního centra v$WC.Příkaz return vytvoří XML, který má <
Step> element, který obsahuje výrobní krok aLocationIDjeho atribut.deklarovat výchozí obor názvů elementu se používá v prologu XQuery tak, aby se všechny deklarace oboru názvů ve výsledném XML zobrazovaly v elementu nejvyšší úrovně. Výsledek tak bude čitelnější. Další informace o výchozích oborech názvů naleznete v tématu Zpracování oborů názvů v XQuery.
Tady je částečný výsledek:
<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>
...
Použití klauzule order by
Řazení v XQuery se provádí pomocí klauzule order by ve výrazu FLWOR. Výrazy řazení předané order by klauzuli musí vracet hodnoty, jejichž typy jsou platné pro gt operátor. Každý výraz řazení musí mít za následek jednu sekvenci s jednou položkou. Ve výchozím nastavení se řazení provádí ve vzestupném pořadí. Volitelně můžete pro každý výraz řazení zadat vzestupné nebo sestupné pořadí.
Poznámka
Porovnání řazení řetězcových hodnot provedených implementací XQuery v SQL Serveru se vždy provádí pomocí binární kolace kódu Unicode.
Následující dotaz načte všechna telefonní čísla pro konkrétního zákazníka ze sloupce AdditionalContactInfo. Výsledky jsou seřazené podle telefonního čísla.
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;
Proces Atomization (XQuery) načte atomické hodnoty <number> prvků před jeho předáním .order by Výraz můžete napsat pomocí data() funkce, ale to není povinné.
order by data($a/act:number[1]) descending
Tady je výsledek:
<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>
Místo deklarování oborů názvů v prologu dotazu je můžete deklarovat pomocí 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;
Můžete také řadit podle hodnoty atributu. Následující dotaz například načte nově vytvořené prvky <Location>, které mají atributy LocationID a LaborHours seřazené podle atributu LaborHours v sestupném pořadí. V důsledku toho se jako první vrátí umístění pracovních center s maximálním počtem pracovních hodin.
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;
Tady je výsledek:
<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"/>
V následujícím dotazu jsou výsledky seřazené podle názvu elementu. Dotaz načte specifikace konkrétního produktu z katalogu produktů. Specifikace jsou podřízené elementu <Specifications>.
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;
Všimněte si následujících věcí z předchozího dotazu:
Výraz
/p1:ProductDescription/p1:Specifications/*vrátí podřízené prvky <Specifications>.Výraz
order by (local-name($a))seřadí sekvenci podle místní části názvu elementu.
Tady je výsledek:
<Color>Available in most colors</Color>
<Material>Aluminum Alloy</Material>
<ProductLine>Mountain bike</ProductLine>
<RiderExperience>Advanced to Professional riders</RiderExperience>
<Style>Unisex</Style>
Uzly, ve kterých výraz řazení vrací prázdné, jsou seřazeny na začátek sekvence, jak je znázorněno v následujícím příkladu:
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
');
Tady je výsledek:
<Person />
<Person Name="A" />
<Person Name="B" />
Můžete zadat více kritérií řazení, jak je znázorněno v následujícím příkladu. Dotaz v tomto příkladu seřadí <Employee> elementy nejprve podle názvu a potom podle hodnot atributů Administrator.
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
');
Tady je výsledek:
<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" />
Omezení
Toto jsou omezení:
Výrazy řazení musí být homogenní. To je staticky zaškrtnuté.
Řazení prázdných sekvencí nelze řídit.
Nejméně prázdná, prázdná největší a kolační klíčová slova
order bynejsou podporována.