Delen via


XQuery en statisch typen

van toepassing op:SQL Server-

XQuery in SQL Server is een statisch getypte taal. Dit houdt in dat er typefouten optreden tijdens het compileren van query's wanneer een expressie een waarde retourneert met een type of kardinaliteit die niet wordt geaccepteerd door een bepaalde functie of operator. Daarnaast kan met statische typecontrole ook worden gedetecteerd of een padexpressie in een getypt XML-document onjuist is getypt. De XQuery-compiler past eerst de normalisatiefase toe die de impliciete bewerkingen toevoegt, zoals atomisatie, en voert vervolgens statische typedeductie en statische typecontrole uit.

Statische typedeductie

Statische typedeductie bepaalt het retourtype van een expressie. Dit wordt bepaald door de statische typen invoerparameters en de statische semantiek van de bewerking te gebruiken en het statische type van het resultaat uit te stellen. Het statische type expressie 1 + 2.3 wordt bijvoorbeeld als volgt bepaald:

  • Het statische type 1 is xs:integer en het statische type 2,3 is xs:decimal. Op basis van de dynamische semantiek converteert de statische semantiek van de + bewerking het gehele getal naar een decimaal en retourneert vervolgens een decimaal. Het uitgestelde statische type wordt vervolgens xs:decimale.

Voor niet-getypte XML-exemplaren zijn er speciale typen om aan te geven dat de gegevens niet zijn getypt. Deze informatie wordt gebruikt tijdens het controleren van statische typen en om bepaalde impliciete casts uit te voeren).

Voor getypte gegevens wordt het invoertype afgeleid van de XML-schemaverzameling die de INSTANTIE van het XML-gegevenstype beperkt. Als het schema bijvoorbeeld alleen elementen van het type xs:integertoestaat, zijn de resultaten van een padexpressie die dat element gebruikt nul of meer elementen van het type xs:integer. Dit wordt momenteel uitgedrukt met behulp van een expressie zoals element(age,xs:integer)* waarbij het sterretje (*) de kardinaliteit van het resulterende type aangeeft. In dit voorbeeld kan de expressie resulteren in nul of meer elementen van de naam 'leeftijd' en het type xs:integer. Andere kardinaliteiten zijn precies één en worden uitgedrukt met de naam van het type alleen, nul of één en uitgedrukt met behulp van een vraagteken (?), en 1 of meer en uitgedrukt met behulp van een plusteken (+).

Soms kan de deductie van het statische type afleiden dat een expressie altijd de lege reeks retourneert. Als een padexpressie voor een getypt XML-gegevenstype bijvoorbeeld zoekt naar een <naam> element binnen een <klantelement> element (/klant/naam), maar het schema staat geen <naam toe> binnen een <klant>, leidt de statische typedeductie ertoe dat het resultaat leeg is. Dit wordt gebruikt om onjuiste query's te detecteren en wordt gerapporteerd als een statische fout, tenzij de expressie () of data( () ).

De gedetailleerde deductieregels worden verstrekt in de formele semantiek van de XQuery-specificatie. Microsoft heeft deze slechts enigszins gewijzigd om te werken met getypte XML-gegevenstype-exemplaren. De belangrijkste wijziging van de standaard is dat het impliciete documentknooppunt weet wat het type XML-gegevenstype-exemplaar is. Als gevolg hiervan wordt een padexpressie van het formulier /leeftijd nauwkeurig getypt op basis van die informatie.

Met behulp van SQL Server Profiler-sjablonen en -machtigingenkunt u de statische typen zien die worden geretourneerd als onderdeel van querycompilaties. Als u deze wilt zien, moet uw tracering de XQuery Static Type-gebeurtenis bevatten in de TSQL-gebeurteniscategorie.

Controle van statische typen

Statische typecontrole zorgt ervoor dat de uitvoeringstijd alleen waarden ontvangt die het juiste type voor de bewerking zijn. Omdat de typen niet tijdens runtime hoeven te worden gecontroleerd, kunnen potentiële fouten vroeg in de compilatie worden gedetecteerd. Dit helpt de prestaties te verbeteren. Statisch typen vereist echter dat de queryschrijver voorzichtiger moet zijn bij het formuleren van een query.

Hieronder vindt u de juiste typen die kunnen worden gebruikt:

  • Typen die expliciet zijn toegestaan door een functie of bewerking.

  • Een subtype van een expliciet toegestaan type.

Subtypen worden gedefinieerd op basis van de subtyperegels voor het gebruik van afleiding door beperking of uitbreiding van het XML-schema. Een type S is bijvoorbeeld een subtype van het type T, als alle waarden met het type S ook exemplaren van het type T zijn.

Daarnaast zijn alle gehele getallen ook decimale waarden, op basis van de hiërarchie van het XML-schematype. Niet alle decimale waarden zijn echter gehele getallen. Daarom is een geheel getal een subtype van decimaal, maar niet omgekeerd. De + bewerking staat bijvoorbeeld alleen waarden van bepaalde typen toe, zoals de numerieke typen xs:integer, xs:decimale, xs:floaten xs:double. Als waarden van andere typen, zoals xs:string, worden doorgegeven, wordt door de bewerking een typefout gegenereerd. Dit wordt ook wel sterke typen genoemd. Waarden van andere typen, zoals het atomische type dat wordt gebruikt om niet-getypte XML aan te geven, kunnen impliciet worden geconverteerd naar een waarde van een type dat door de bewerking wordt geaccepteerd. Dit wordt aangeduid als zwak typen.

Als dit vereist is na een impliciete conversie, garandeert een statische typecontrole dat alleen waarden van de toegestane typen met de juiste kardinaliteit worden doorgegeven aan een bewerking. Voor 'tekenreeks' + 1 wordt herkend dat het statische type 'tekenreeks' is xs:string. Omdat dit geen toegestaan type is voor de +-bewerking, wordt er een typefout gegenereerd.

In het geval van het toevoegen van het resultaat van een willekeurige expressie E1 aan een willekeurige expressie E2 (E1 + E2), bepaalt de statische typedeductie eerst de statische typen E1 en E2 en controleert vervolgens de statische typen met de toegestane typen voor de bewerking. Als het statische type E1 bijvoorbeeld een xs:string of een xs:integerkan zijn, veroorzaakt de controle van het statische type een typefout, zelfs als sommige waarden tijdens runtime gehele getallen kunnen zijn. Hetzelfde zou het geval zijn als het statische type E1 xs:integer*. Omdat de + bewerking slechts exact één geheel getal accepteert en E1 nul of meer dan 1 kan retourneren, veroorzaakt de controle van het statische type een fout.

Zoals eerder vermeld, wordt door typedeductie vaak een type afgeleid dat breder is dan wat de gebruiker weet over het type gegevens dat wordt doorgegeven. In deze gevallen moet de gebruiker de query opnieuw schrijven. Enkele typische gevallen zijn onder andere:

  • Het type afgeleid een meer algemeen type, zoals een supertype of een samenvoeging van typen. Als het type een atomisch type is, moet u de cast-expressie of constructorfunctie gebruiken om het werkelijke statische type aan te geven. Als het uitgestelde type van de expressie E1 bijvoorbeeld een keuze is tussen xs:string of xs:integer en de toevoeging vereist xs:integer, moet u xs:integer(E1) + E2 schrijven in plaats van E1+E2. Deze expressie kan mislukken tijdens runtime als er een tekenreekswaarde optreedt die niet kan worden gecast naar xs:integer. De expressie geeft nu echter de controle van het statische type door. Deze expressie is toegewezen aan de lege reeks.

  • Het type geeft een hogere kardinaliteit af dan wat de gegevens daadwerkelijk bevatten. Dit gebeurt vaak omdat het xml- gegevenstype meer dan één element op het hoogste niveau kan bevatten en een XML-schemaverzameling dit niet kan beperken. Als u het statische type wilt verminderen en wilt garanderen dat er inderdaad maximaal één waarde wordt doorgegeven, moet u het positionele predicaat [1]gebruiken. Als u bijvoorbeeld 1 wilt toevoegen aan de waarde van het kenmerk c van het element b onder een element op het hoogste niveau, moet u write (/a/b/@c)[1]+1. Daarnaast kan het trefwoord DOCUMENT samen met een XML-schemaverzameling worden gebruikt.

  • Sommige bewerkingen verliezen typegegevens tijdens deductie. Als het type van een knooppunt bijvoorbeeld niet kan worden bepaald, wordt het anyType. Dit wordt niet impliciet naar een ander type gecast. Deze conversies vinden vooral plaats tijdens de navigatie met behulp van de bovenliggende as. Vermijd het gebruik van dergelijke bewerkingen en herschrijf de query als de expressie een statische typefout veroorzaakt.

Typecontrole van samenvoegtypen

Samenvoegtypen vereisen zorgvuldige verwerking vanwege typecontrole. Twee van de problemen worden geïllustreerd in de volgende voorbeelden.

Voorbeeld: Functie boven samenvoegtype

Overweeg een elementdefinitie voor <r> van een samenvoegtype:

<xs:element name="r">  
<xs:simpleType>  
   <xs:union memberTypes="xs:int xs:float xs:double"/>  
</xs:simpleType>  
</xs:element>  

Binnen XQuery-context retourneert de functie gemiddelde fn:avg (//r) een statische fout, omdat de XQuery-compiler geen waarden van verschillende typen kan toevoegen (xs:int, xs:float of xs:double) voor de <r> elementen in het argument van fn:avg(). U lost dit op door de functie aanroep te herschrijven als fn:avg(for $r in //r return $r cast as xs:double ?).

Voorbeeld: Operator boven samenvoegtype

Voor de optellingsbewerking ('+') zijn nauwkeurige typen operanden vereist. Als gevolg hiervan retourneert de expressie (//r)[1] + 1 een statische fout met de eerder beschreven typedefinitie voor element <r>. Een oplossing is het herschrijven als (//r)[1] cast as xs:int? +1, waarbij de '?' 0 of 1 exemplaren aangeeft. SQL Server vereist 'cast as' met '?' omdat elke cast de lege reeks kan veroorzaken als gevolg van runtimefouten.

Zie ook

XQuery Language Reference (SQL Server)