Zu diesem Zweck möchten Sie die .exist()
XML-Funktion verwenden, da sie einen BIT-Wert (dh einen booleschen Wert) zurückgibt, der angibt, ob die XQuery etwas findet oder nicht.
Um die nicht statische Position eines Elements zu behandeln, verwenden Sie entweder *
(zeigt an, dass alle Knoten einer bestimmten Ebene überprüft werden sollen, jedoch nicht andere Ebenen) oder //
(zeigt an, dass alle Knoten auf dieser Ebene und darunter überprüft werden sollen).
In den folgenden Beispielen wird die Beispielabfrage aus der Frage als Basis verwendet, und es werden einige Testfälle hinzugefügt, um das Element auf verschiedenen Ebenen zu platzieren. Außerdem wird ein Testfall hinzugefügt, der den Namen ändert, um zu zeigen, dass die XQuery nicht nur alles auswählt.
Test Setup (einmal ausführen)
SET NOCOUNT ON;
CREATE TABLE #Table (ID INT NOT NULL, XmlCol XML);
INSERT INTO #Table (ID, XmlCol) VALUES (1, N'
<root>
<MCTClientName>John</MCTClientName>
<MCTClientCity>Palm Beach</MCTClientCity>
<MCTLocations>
<MCTLocation>
<Address>1234 Main Street</Address>
<ContactFName>Chris</ContactFName>
<ContactLName>Brandt</ContactLName>
</MCTLocation>
</MCTLocations>
</root>');
INSERT INTO #Table (ID, XmlCol) VALUES (2, N'
<root>
<MCTClientName>John</MCTClientName>
<MCTClientCity>Palm Beach</MCTClientCity>
<MCTLocations>
<MCTLocation>
<Address>1234 Main Street</Address>
<ContactFName>Chris</ContactFName>
<ContactLName>Grandt</ContactLName>
</MCTLocation>
</MCTLocations>
</root>');
INSERT INTO #Table (ID, XmlCol) VALUES (3, N'
<root>
<MCTClientName>John</MCTClientName>
<MCTClientCity>Palm Beach</MCTClientCity>
<MCTLocations>
<MCTLocation>
<Address>1234 Main Street</Address>
<ContactFName>Chris</ContactFName>
</MCTLocation>
</MCTLocations>
<ContactLName>Brandt</ContactLName>
</root>');
INSERT INTO #Table (ID, XmlCol) VALUES (4, N'
<root>
<MCTClientName>John</MCTClientName>
<MCTClientCity>Palm Beach</MCTClientCity>
<MCTLocations>
<MCTLocation>
<Address>1234 Main Street</Address>
<ContactFName>Chris</ContactFName>
</MCTLocation>
<NewElement>
<SubElement>
<ContactLName>Brandt</ContactLName>
</SubElement>
</NewElement>
</MCTLocations>
</root>');
INSERT INTO #Table (ID, XmlCol) VALUES (5, N'
<root>
<MCTClientName>John</MCTClientName>
<MCTClientCity>Palm Beach</MCTClientCity>
<MCTLocations>
<MCTLocation>
<Address>1234 Main Street</Address>
<ContactFName>Chris</ContactFName>
</MCTLocation>
<NewerElement>
<ContactLName>Brandt</ContactLName>
</NewerElement>
</MCTLocations>
</root>');
INSERT INTO #Table (ID, XmlCol) VALUES (6, N'
<root>
<MCTClientName>John</MCTClientName>
<MCTClientCity>Palm Beach</MCTClientCity>
<MCTLocations>
<MCTLocation>
<Address>1234 Main Street</Address>
<ContactFName>Chris</ContactFName>
</MCTLocation>
<NewerElement>
</NewerElement>
</MCTLocations>
</root>
<ContactLName>Brandt</ContactLName>
');
Test 1 ( *
anstelle eines Knotennamens)
Dadurch werden alle Knoten auf der angegebenen Ebene überprüft, die in diesem Fall knapp darunter liegt <root>
. Andere Ebenen werden jedoch nicht überprüft.
SELECT *
FROM #Table tmp
WHERE tmp.[XmlCol].exist(N'/*/ContactLName[text()="Brandt"]') = 1;
Gibt eine Zeile mit dem ID
Wert 3 zurück.
Test 2 ( *
anstelle eines Knotennamens)
Dadurch werden alle Knoten auf der angegebenen Ebene überprüft, die in diesem Fall knapp darunter liegt <root><MCTLocations>
. Andere Ebenen werden jedoch nicht überprüft.
SELECT *
FROM #Table tmp
WHERE tmp.[XmlCol].exist(N'/root/MCTLocations/*/ContactLName[text()="Brandt"]') = 1;
Gibt Zeilen mit den ID
Werten 1 und 5 zurück.
Test 3 ( //
anstelle eines Knotennamens)
Dadurch werden alle Knoten überprüfen beginnend auf der angegebenen Ebene, die in diesem Fall ist knapp <root><MCTLocations>
, und unten .
SELECT *
FROM #Table tmp
WHERE tmp.[XmlCol].exist(N'/root/MCTLocations//ContactLName[text()="Brandt"]') = 1;
Gibt Zeilen mit den ID
Werten 1, 4 und 5 zurück.
Test 4 ( /*
oder */
anstelle eines Knotennamens)
SELECT *
FROM #Table tmp
WHERE tmp.[XmlCol].exist(N'*//ContactLName[text()="Brandt"]') = 1;
-- and:
SELECT *
FROM #Table tmp
WHERE tmp.[XmlCol].exist(N'//*/ContactLName[text()="Brandt"]') = 1;
Beide geben Zeilen mit den ID
Werten 1, 3, 4 und 5 zurück.
Diese geben keine Zeilen-ID von 6 zurück, da *
sie ein Platzhalter für einen einzelnen Knoten sind, daher würde die höchste zulässige Ebene unter <root>
(oder einem Knoten der obersten Ebene) liegen.
Test 5 ( //
auf der obersten Ebene)
Dadurch werden alle Knoten überprüft, die auf der obersten Ebene beginnen.
SELECT *
FROM #Table tmp
WHERE tmp.[XmlCol].exist(N'//ContactLName[text()="Brandt"]') = 1;
Gibt Zeilen mit den ID
Werten 1, 3, 4, 5 und 6 zurück.
Test 6 (lokalen Variablenwert für Elementtext in XQuery verwenden)
DECLARE @Name NVARCHAR(50) = N'Brandt';
SELECT *
FROM #Table tmp
WHERE tmp.[XmlCol].exist(N'//ContactLName[text()=sql:variable("@Name")]') = 1;
SET @Name = N'Grandt';
-- exact same query, just different value in the variable
SELECT *
FROM #Table tmp
WHERE tmp.[XmlCol].exist(N'//ContactLName[text()=sql:variable("@Name")]') = 1;
Die erste Abfrage gibt Zeilen mit den ID
Werten 1, 3, 4, 5 und 6 zurück.
Die zweite Abfrage gibt eine Zeile mit dem ID
Wert 2 zurück.
Test 7 (Funktion und Zeichenfolgenliteral für Elementnamen in XQuery verwenden)
SELECT *
FROM #Table tmp
WHERE tmp.[XmlCol].exist(N'//.[local-name()="NewerElement"]') = 1;
Gibt Zeilen mit den ID
Werten 5 und 6 zurück.
Test 8 (Funktion mit lokalem Variablenwert für Elementnamen in XQuery verwenden)
DECLARE @Node NVARCHAR(50) = N'SubElement';
SELECT *
FROM #Table tmp
WHERE tmp.[XmlCol].exist(N'//.[local-name()=sql:variable("@Node")]') = 1;
Gibt eine Zeile mit dem ID
Wert 4 zurück.
Test 9 (alle Teile zusammenfügen)
DECLARE @NodeName NVARCHAR(50) = N'ContactLName',
@NodeText NVARCHAR(500) = N'Brandt';
SELECT *
FROM #Table tmp
WHERE tmp.[XmlCol].exist(N'//.[local-name()=sql:variable("@NodeName")]
[text()=sql:variable("@NodeText")]') = 1;
Gibt Zeilen mit den ID
Werten 1, 3, 4, 5 und 6 zurück.
Allgemeiner XML-Hinweis:
XML-Daten (in SQL Server) werden wie NVARCHAR
/ als UTF-16 Little Endian codiert NCHAR
. Daher ist es am besten, Sting-Literalen ein Großbuchstaben voranzustellen - N
wenn der Wert wirklich XML ist.