Výrazy cesty – určení predikátů
platí pro:SQL Server
Jak je popsáno v tématu, Výrazy cesty v XQuery, krok osy ve výrazu cesty obsahuje následující komponenty:
osu.
Test uzlu Další informace najdete v tématu Určení testu uzlu v kroku výrazu cesty.
Nula nebo více predikátů. Toto je volitelné.
Volitelný predikát je třetí částí kroku osy ve výrazu cesty.
Predikáty
Predikát slouží k filtrování sekvence uzlů použitím zadaného testu. Predikát výraz je uzavřený v hranaté závorce a je vázán na poslední uzel ve výrazu cesty.
Předpokládejme například, že je deklarována hodnota parametru SQL (x) xml datového typu, jak je znázorněno v následujícím příkladu:
declare @x xml
set @x = '
<People>
<Person>
<Name>John</Name>
<Age>24</Age>
</Person>
<Person>
<Name>Goofy</Name>
<Age>54</Age>
</Person>
<Person>
<Name>Daffy</Name>
<Age>30</Age>
</Person>
</People>
'
V tomto případě jsou následující platné výrazy, které používají predikát hodnotu [1] na každé ze tří různých úrovní uzlů:
select @x.query('/People/Person/Name[1]')
select @x.query('/People/Person[1]/Name')
select @x.query('/People[1]/Person/Name')
Všimněte si, že v každém případě predikát vytvoří vazbu k uzlu ve výrazu cesty, ve kterém se použije. Například první výraz cesty vybere první prvek <Name
> v rámci každého uzlu /People/Person a se zadanou instancí XML vrátí následující:
<Name>John</Name><Name>Goofy</Name><Name>Daffy</Name>
Druhý výraz cesty však vybere všechny prvky <Name
>, které jsou pod prvním uzlem /People/Person. Proto vrátí následující:
<Name>John</Name>
Závorky lze také použít ke změně pořadí vyhodnocení predikátu. Například v následujícím výrazu se sada závorek používá k oddělení cesty (/People/Person/Name) od predikátu [1]:
select @x.query('(/People/Person/Name)[1]')
V tomto příkladu se změní pořadí, ve kterém se použije predikát. Důvodem je to, že uzavřená cesta se nejprve vyhodnotí (/People/Person/Name) a pak se na sadu, která obsahuje všechny uzly, které odpovídají uzavřené cestě, použije operátor predikátu [1]. Bez závorek se pořadí operace bude lišit v tom, že [1] se použije jako test child::Name
uzlu, podobně jako v příkladu výrazu první cesty.
Kvantifikátory a predikáty
Kvantifikátory lze použít a přidat vícekrát do složených závorek samotného predikátu. Například při použití předchozího příkladu je platné použití více než jednoho kvantifikátoru v rámci komplexního dílčího výrazu predikátu.
select @x.query('/People/Person[contains(Name[1], "J") and xs:integer(Age[1]) < 40]/Name/text()')
Výsledek výrazu predikátu je převeden na logickou hodnotu a označuje se jako predikát pravdivá hodnota. Ve výsledku se vrátí pouze uzly v sekvenci, pro které je hodnota pravdy predikátu pravdivá. Všechny ostatní uzly se zahodí.
Například následující výraz cesty obsahuje v druhém kroku predikát:
/child::root/child::Location[attribute::LocationID=10]
Podmínka určená tímto predikátem se použije pro všechny podřízené prvky elementu <Location
>. Výsledkem je, že se vrátí pouze umístění pracovního centra, jejichž hodnota atributu LocationID je 10.
Předchozí výraz cesty se provede v následujícím příkazu SELECT:
SELECT Instructions.query('
declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
/child::AWMI:root/child::AWMI:Location[attribute::LocationID=10]
')
FROM Production.ProductModel
WHERE ProductModelID=7
Výpočetní predikát pravdivých hodnot
Následující pravidla se použijí k určení hodnoty pravdy predikátu podle specifikací XQuery:
Pokud je hodnota výrazu predikátu prázdná sekvence, hodnota pravdy predikátu je False.
Například:
SELECT Instructions.query(' declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"; /child::AWMI:root/child::AWMI:Location[attribute::LotSize] ') FROM Production.ProductModel WHERE ProductModelID=7
Výraz cesty v tomto dotazu vrátí pouze ty, <
Location
> uzly prvků, které mají zadaný atribut LotSize. Pokud predikát vrátí prázdnou sekvenci pro konkrétní <Location
>, toto umístění pracovního centra se ve výsledku nevrátí.Predikátové hodnoty mohou být pouze xs:integer, xs:Boolean nebo node*. U uzlu*se predikát vyhodnotí jako Pravda, pokud existují nějaké uzly, a nepravda pro prázdnou sekvenci. Jakýkoli jiný číselný typ, například dvojitý a plovoucí typ, generuje statickou chybu při psaní. Predikát pravdivá hodnota výrazu je True, pokud je výsledné celé číslo rovno hodnotě kontextové pozice. Také pouze celočíselné literály a funkce last() snižují kardinalitu filtrovaného výrazu kroku na 1.
Například následující dotaz načte třetí podřízený uzel elementu <
Features
> elementu.SELECT CatalogDescription.query(' declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription"; declare namespace wm="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain"; /child::PD:ProductDescription/child::PD:Features/child::*[3] ') FROM Production.ProductModel WHERE ProductModelID=19
Všimněte si následujících věcí z předchozího dotazu:
Třetí krok ve výrazu určuje predikát výraz, jehož hodnota je 3. Proto predikát pravdivá hodnota tohoto výrazu je True pouze pro uzly, jejichž kontextová pozice je 3.
Třetí krok také určuje zástupný znak (*), který označuje všechny uzly v testu uzlu. Predikát však filtruje uzly a vrátí pouze uzel na třetí pozici.
Dotaz vrátí třetí podřízený uzel podřízeného elementu <
Features
> podřízený prvek <ProductDescription
> podřízený prvek kořenového adresáře dokumentu.
Pokud je hodnota výrazu predikátu jedna jednoduchá hodnota typu Boolean, predikát pravdivá hodnota se rovná hodnotě predikátu výrazu predikátu.
Například následující dotaz je určen pro proměnnou typu xml, která obsahuje instanci XML, instanci XML průzkumu zákazníka. Dotaz načte zákazníky, kteří mají děti. V tomto dotazu by to bylo <HasChildren>1</HasChildren>.
declare @x xml set @x=' <Survey> <Customer CustomerID="1" > <Age>27</Age> <Income>20000</Income> <HasChildren>1</HasChildren> </Customer> <Customer CustomerID="2" > <Age>27</Age> <Income>20000</Income> <HasChildren>0</HasChildren> </Customer> </Survey> ' declare @y xml set @y = @x.query(' for $c in /child::Survey/child::Customer[( child::HasChildren[1] cast as xs:boolean ? )] return <CustomerWithChildren> { $c/attribute::CustomerID } </CustomerWithChildren> ') select @y
Všimněte si následujících věcí z předchozího dotazu:
Výraz v smyčky má dva kroky a druhý krok určuje predikát. Hodnota tohoto predikátu je logická hodnota typu. Pokud je tato hodnota Pravdivá, hodnota pravdy predikátu je také Pravda.
Dotaz vrátí podřízené prvky <
Customer
>, jejichž predikát hodnota je True, <Survey> podřízený prvek kořene dokumentu. Toto je výsledek:<CustomerWithChildren CustomerID="1"/>
Pokud je hodnota výrazu predikátu posloupnost, která obsahuje alespoň jeden uzel, predikát pravdivá hodnota je Pravda.
Následující dotaz například načte Kód ProductModelID pro modely produktů, jejichž popis katalogu XML obsahuje alespoň jednu funkci, podřízený prvek elementu <Features
>, z oboru názvů přidruženého k předponě wm.
SELECT ProductModelID
FROM Production.ProductModel
WHERE CatalogDescription.exist('
declare namespace PD="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
declare namespace wm="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain";
/child::PD:ProductDescription/child::PD:Features[wm:*]
') = 1
Všimněte si následujících věcí z předchozího dotazu:
Klauzule WHERE určuje metodu exist() (datový typ XML).
Výraz cesty uvnitř exist() metoda určuje predikát v druhém kroku. Pokud výraz predikátu vrátí sekvenci alespoň jedné funkce, hodnota pravdy tohoto predikátového výrazu je True. V tomto případě, protože exist() metoda vrátí True, ProductModelID je vrácen.
Filtry statického psaní a predikátu
Predikáty mohou také ovlivnit staticky odvozený typ výrazu. Celočíselné literály a last() funkce snižují kardinalitu filtrovaného výrazu kroku na maximálně jednu.