Kommentar
Å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
XQuery i SQL Server är ett statiskt typat språk. Det vill säga, det ger typfel under frågekompilering när ett uttryck returnerar ett värde som har en typ eller kardinalitet som inte accepteras av en viss funktion eller operator. Dessutom kan statisk typkontroll också upptäcka om ett väguttryck på ett typat XML-dokument har blivit feltypat. XQuery-kompilatorn tillämpar först normaliseringsfasen som lägger till implicita operationer, såsom atomisering, och utför sedan statisk typinferens och statisk typkontroll.
Statisk typinferens
Statisk typinferens bestämmer returtypen för ett uttryck. Den bestämmer detta genom att ta de statiska typerna av indataparametrarna och den statiska semantiken för operationen och härleda den statiska typen av resultatet. Till exempel bestäms den statiska typen av uttrycket 1 + 2,3 på följande sätt:
- Den statiska typen av 1 är xs:heltal och den statiska typen av 2,3 är xs:decimal. Baserat på den dynamiska semantiken omvandlar den statiska semantiken i operationen + heltalet till en decimal och returnerar sedan en decimal. Den härledda statiska typen skulle då vara xs:decimal.
För otypade XML-instanser finns det speciella typer som indikerar att datan inte har skrivits. Denna information används vid statisk typkontroll och för att utföra vissa implicita casts.
För typad data härleds indatatypen från XML-schemasamlingen som begränsar XML-datatypinstansen. Till exempel, om schemat endast tillåter element av typen xs:heltals, kommer resultatet av ett väguttryck med det elementet att vara noll eller fler element av typen xs:heltal. Detta uttrycks för närvarande med ett uttryck som element(age,xs:integer)* där asterisken (*) anger kardinaliteten för den resulterande typen. I detta exempel kan uttrycket resultera i noll eller fler element av namnet "ålder" och typen xs:heltal. Andra kardinaliteter är exakt ett och uttrycks genom att använda typnamnet ensamt, noll eller ett och uttrycks med ett frågetecken (?), och 1 eller flera samt uttrycks med ett plustecken (+).
Ibland kan den statiska typinferensen dra slutsatsen att ett uttryck alltid kommer att returnera den tomma sekvensen. Till exempel, om ett väguttryck på en typad XML-datatyp letar efter ett <namnelement> inuti ett <kundelement> (/customer/name), men schemat inte tillåter ett <namn> inuti en <kund>, kommer den statiska typinferensen att dra slutsatsen att resultatet kommer att vara tomt. Detta kommer att användas för att upptäcka felaktiga frågor och rapporteras som ett statiskt fel, om inte uttrycket var () eller data( () ).
De detaljerade slutledningsreglerna finns i den formella semantiken i XQuery-specifikationen. Microsoft har endast modifierat dessa marginellt för att fungera med typade XML-datatypinstanser. Den viktigaste förändringen från standarden är att den implicita dokumentnoden känner till typen av XML-datatypinstans. Som ett resultat kommer ett väguttryck av formen /age att typas exakt baserat på den informationen.
Genom att använda SQL Server Profiler Templates and Permissions kan du se de statiska typerna som returneras som en del av frågekompileringar. För att se dessa måste din spårning inkludera XQuery Static Type-händelsen i TSQL-händelsekategorin.
Statisk typkontroll
Statisk typkontroll säkerställer att körtidsexekveringen endast tar emot värden som är av rätt typ för operationen. Eftersom typerna inte behöver kontrolleras vid körning kan potentiella fel upptäckas tidigt i kompileringen. Detta hjälper till att förbättra prestandan. Statisk typning kräver dock att frågeförfattaren är mer försiktig när han formulerar en fråga.
Följande är lämpliga typer som kan användas:
Typer som uttryckligen tillåts av en funktion eller operation.
En subtyp av en uttryckligen tillåten typ.
Subtyper definieras baserat på deltypningsreglerna för att använda härledning genom begränsning eller utvidgning av XML-schemat. Till exempel är en typ S en undertyp av typ T, om alla värden som har typen S också är instanser av typen T.
Dessutom är alla heltalsvärden också decimalvärden, baserat på XML-schematyphierarkin. Dock är inte alla decimalvärden heltal. Därför är ett heltal en subtyp av decimal, men inte tvärtom. Till exempel tillåter operationen + endast värden av vissa typer, såsom de numeriska typerna xs:heltal, xs:decimal, xs:flyttail och xs:dubbel. Om värden av andra typer, såsom xs:string, passeras, ger operationen ett typfel. Detta kallas stark typning. Värden av andra typer, såsom den atomära typen som används för att ange otypad XML, kan implicit konverteras till ett värde av en typ som operationen accepterar. Detta kallas svag typning.
Om det krävs efter en implicit konvertering garanterar statisk typkontroll att endast värden av de tillåtna typerna med korrekt kardinalitet skickas till en operation. För "string" + 1 känner den igen att den statiska typen av "string" är xs:string. Eftersom detta inte är en tillåten typ för operationen + uppstår ett typfel.
I fallet med att lägga till resultatet av ett godtyckligt uttryck E1 till ett godtyckligt uttryck E2 (E1 + E2), bestämmer statisk typinferens först de statiska typerna för E1 och E2 och kontrollerar sedan deras statiska typer med tillåtna typer för operationen. Till exempel, om den statiska typen av E1 kan vara antingen en xs:sträng eller en xs:heltalskontroll, ger den statiska typkontrollen ett typfel, även om vissa värden vid körning kan vara heltal. Samma sak skulle gälla om den statiska typen av E1 var xs:heltals*. Eftersom operationen + endast accepterar exakt ett heltalsvärde och E1 kan returnera noll eller mer än 1, ger den statiska typkontrollen ett fel.
Som nämnts tidigare innebär typinferens ofta en typ som är bredare än vad användaren vet om typen av data som skickas vidare. I dessa fall måste användaren skriva om frågan. Några typiska fall inkluderar följande:
Typen antyder en mer generell typ, såsom en supertyp eller en union av typer. Om typen är atomär bör du använda cast-uttrycket eller konstruktorfunktionen för att ange den faktiska statiska typen. Till exempel, om den härledda typen av uttrycket E1 är ett val mellan xs:sträng eller xs:heltal och additionen kräver xs:heltal, bör du skriva
xs:integer(E1) + E2istället förE1+E2. Detta uttryck kan misslyckas vid körning om ett strängvärde påträffas som inte kan omvandlas till xs:heltal. Uttrycket kommer dock nu att klara den statiska typkontrollen. Detta uttryck avbildas till den tomma sekvensen.Typen antyder en högre kardinalitet än vad datan faktiskt innehåller. Detta sker ofta, eftersom xml-datatypen kan innehålla mer än ett toppnivåelement, och en XML-schemasamling kan inte begränsa detta. För att minska den statiska typen och garantera att det verkligen finns högst ett värde som passeras, bör du använda positionspredikatet
[1]. Till exempel, för att lägga till 1 till värdet av attributetcför elementetbunder elementets högsta nivå, måstewrite (/a/b/@c)[1]+1du . Dessutom kan nyckelordet DOCUMENT användas tillsammans med en XML-schemasamling.Vissa operationer förlorar typinformation under inferensen. Till exempel, om typen av en nod inte kan bestämmas, blir den anyType. Detta är inte implicit avsett för någon annan typ. Dessa omvandlingar sker särskilt under navigering genom att använda föräldraaxeln. Du bör undvika att använda sådana operationer och skriva om frågan om uttrycket kommer att skapa ett statiskt typfel.
Typkontroll av fackföreningstyper
Fackliga typer kräver noggrann hantering på grund av typkontroll. Två av problemen illustreras i följande exempel.
Exempel: Funktion över Union Type
Betrakta en elementdefinition för <r> av uniontyp:
<xs:element name="r">
<xs:simpleType>
<xs:union memberTypes="xs:int xs:float xs:double"/>
</xs:simpleType>
</xs:element>
Inom XQuery-kontexten returnerar funktionen "genomsnittfn:avg (//r)" ett statiskt fel, eftersom XQuery-kompilatorn inte kan lägga till värden av olika typer (xs:int, xs:float eller xs:double) för <r> elementen i argumentet fn:avg(). För att lösa detta, skriv om funktionsanropet som fn:avg(for $r in //r return $r cast as xs:double ?).
Exempel: Operatör över Union Type
Additionsoperationen ('+') kräver precisa typer av operanderna. Som ett resultat returnerar uttrycket (//r)[1] + 1 ett statiskt fel som har den tidigare beskrivna typdefinitionen för elementetr<> . En lösning är att skriva om den som (//r)[1] cast as xs:int? +1, där "?" indikerar 0 eller 1 förekomster. SQL Server kräver "cast as" med "?", eftersom vilken cast som helst kan orsaka den tomma sekvensen som ett resultat av körtidsfel.