Richtlinien zum Verwenden von Methoden des xml-Datentyps
In diesem Thema werden Richtlinien zum Verwenden der xml-Datentypmethoden beschrieben.
Die PRINT-Anweisung
Die Methoden des xml-Datentyps können nicht in der PRINT-Anweisung verwendet werden, wie das folgende Beispiel zeigt. Die Methoden des xml-Datentyps werden als Unterabfragen behandelt, und Unterabfragen sind in der PRINT-Anweisung nicht zulässig. Aus diesem Grund gibt das folgende Beispiel einen Fehler zurück:
DECLARE @x xml
SET @x = '<root>Hello</root>'
PRINT @x.value('/root[1]', 'varchar(20)') -- will not work because this is treated as a subquery (select top 1 col from table)
Eine mögliche Lösung besteht darin, zuerst das Ergebnis der value()-Methode einer Variablen vom xml-Typ zuzuweisen und dann diese Variable in der Abfrage anzugeben.
DECLARE @x xml
DECLARE @c varchar(max)
SET @x = '<root>Hello</root>'
SET @c = @x.value('/root[1]', 'varchar(11)')
PRINT @c
Die GROUP BY-Klausel
Die Methoden des xml-Datentyps werden intern als Unterabfragen behandelt. Da GROUP BY einen Skalarwert erfordert und keine Aggregate oder Unterabfragen zulässt, können Sie die Methoden des xml-Datentyps nicht in der GROUP BY-Klausel angeben. Eine mögliche Lösung besteht im Aufrufen einer benutzerdefinierten Funktion, innerhalb derer XML-Methoden verwendet werden.
Erstellen von Fehlerberichten
Sollte ein Fehler auftreten, lösen die Methoden des xml-Datentyps einen einzelnen Fehler im folgenden Format aus:
Msg errorNumber, Level levelNumber, State stateNumber:
XQuery [database.table.method]: description_of_error
Beispiel:
Msg 2396, Level 16, State 1:
XQuery [xmldb_test.xmlcol.query()]: Attribute may not appear outside of an element
Singleton-Überprüfungen
Positionsschritte, Funktionsparameter und Operatoren, die Singleton-Elemente benötigen, geben einen Fehler zurück, wenn der Compiler nicht ermitteln kann, ob zur Laufzeit ein Singleton-Element sichergestellt ist. Dieses Problem tritt häufig bei nicht typisierten Daten auf. So erfordert z. B. die Suche eines Attributs ein übergeordnetes Singleton-Element. Dabei ist eine Ordinalzahl ausreichend, die einen einzelnen übergeordneten Knoten auswählt. Die Auswertung einer node()-value()-Kombination zum Extrahieren von Attributwerten erfordert möglicherweise keine Angabe der Ordinalzahl. Dies ist im nächsten Beispiel dargestellt.
Beispiel: Bekanntes Singleton
In diesem Beispiel generiert die nodes()-Methode eine separate Zeile für jedes <book>-Element. Die value()-Methode, die in einem <book>-Knoten ausgewertet wird, extrahiert den Wert von @genre und stellt, da es sich um ein Attribut handelt, ein Singleton-Element dar.
SELECT nref.value('@genre', 'varchar(max)') LastName
FROM T CROSS APPLY xCol.nodes('//book') AS R(nref)
Das XML-Schema wird zur Typprüfung von typisiertem XML verwendet. Wenn ein Knoten im XML-Schema als ein Singleton angegeben ist, verwendet der Compiler diese Informationen, und es tritt kein Fehler auf. Ansonsten ist eine Ordinalzahl erforderlich, die einen einzelnen Knoten auswählt. Insbesondere bei Verwendung einer descendant-or-self-Achse (//) wie in /book//title geht die Singleton-Kardinalitätsinferenz für das Element <title> verloren; dies gilt auch bei einer entsprechenden Angabe durch das XML-Schema. Deshalb sollten Sie ihn als (/book//title)[1] umschreiben.
Sie müssen sich des Unterschiedes zwischen //first-name[1] und (//first-name)[1] für die Typüberprüfung bewusst sein. Das erstgenannte Element gibt eine Sequenz von <first-name>-Knoten zurück, in der die einzelnen Knoten jeweils den äußeren linken <first-name>-Knoten der gleichgeordneten Elemente darstellen. Das letztgenannte Element gibt den ersten <first-name>-Singleton-Knoten in der Dokumentreihenfolge der XML-Instanz zurück.
Beispiel: Verwenden von value()
Die folgende Abfrage einer nicht typisierten XML-Spalte führt zu einem statischen Kompilierungsfehler. Das liegt daran, dass value() einen Singleton-Knoten als erstes Argument erwartet und der Compiler nicht feststellen kann, ob nur ein <last-name>-Knoten zur Laufzeit auftritt:
SELECT xCol.value('//author/last-name', 'nvarchar(50)') LastName
FROM T
Es folgt eine Projektmappe, die Sie in Betracht ziehen könnten:
SELECT xCol.value('//author/last-name[1]', 'nvarchar(50)') LastName
FROM T
Der Fehler wird auf diese Weise jedoch nicht behoben, da in jeder XML-Instanz mehrere <author>-Knoten vorhanden sein können. Die folgende umgeschriebene Version ist jedoch funktionsfähig:
SELECT xCol.value('(//author/last-name/text())[1]', 'nvarchar(50)') LastName
FROM T
Diese Abfrage gibt den Wert des ersten <last-name>-Elements in jeder XML-Instanz zurück.