Freigeben über


Hinzufügen von Namespaces zu Abfragen mit WITH XMLNAMESPACES

Gilt für: SQL Server Azure SQL-Datenbank Azure SQL Managed Instance

WITH XMLNAMESPACES (Transact-SQL) bietet folgende Namespace-URI-Unterstützung:

Verwendung von WITH XMLNAMESPACES in FOR XML-Abfragen

Mit WITH XMLNAMESPACES können Sie XML-Namespaces in FOR XML-Abfragen einbeziehen. Nehmen Sie beispielsweise folgende FOR XML-Abfrage:

SELECT ProductID, Name, Color
FROM   Production.Product
WHERE  ProductID IN (316, 317)
FOR XML RAW;

Dies ist das Ergebnis:

<row ProductID="316" Name="Blade" />
<row ProductID="317" Name="LL Crankarm" Color="Black" />

Um Namespaces zu dem durch die FOR XML-Abfrage erstellten XML hinzuzufügen, legen Sie zuerst mit der WITH NAMESPACES-Klausel die Zuordnungen der Namespacepräfixe zu URIs fest. Verwenden Sie anschließend in der folgenden geänderten Abfrage die Namespacepräfixe, um die in der Abfrage verwendeten Namen festzulegen. Die WITH XMLNAMESPACES-Klausel legt die Zuordnung des Namespace-Präfixes (ns1) zum URI (uri) fest. Das ns1 -Präfix wird dann beim Festlegen der Element- und Attributnamen verwendet, die durch die FOR XML-Abfrage erstellt werden sollen.

WITH XMLNAMESPACES ('uri' as ns1)
SELECT ProductID as 'ns1:ProductID',
       Name      as 'ns1:Name',
       Color     as 'ns1:Color'
FROM  Production.Product
WHERE ProductID IN (316, 317)
FOR XML RAW ('ns1:Prod'), ELEMENTS;

Das XML-Ergebnis enthält die Namespacepräfixe:

<ns1:Prod xmlns:ns1="uri">
  <ns1:ProductID>316</ns1:ProductID>
  <ns1:Name>Blade</ns1:Name>
</ns1:Prod>
<ns1:Prod xmlns:ns1="uri">
  <ns1:ProductID>317</ns1:ProductID>
  <ns1:Name>LL Crankarm</ns1:Name>
  <ns1:Color>Black</ns1:Color>
</ns1:Prod>

Für die WITH XMLNAMESPACES-Klausel gilt Folgendes:

  • Sie wird nur im RAW-, AUTO- und PATH-Modus der FOR XML-Abfragen unterstützt. Der EXPLICIT-Modus wird nicht unterstützt.

  • Sie wirkt sich nur auf die Namespacepräfixe von FOR XML-Abfragen und auf die xml -Datentypmethode aus – aber nicht auf den XML-Parser. Die folgende Abfrage gibt beispielsweise einen Fehler zurück, weil das XML-Dokument keine Namespacedeklaration für das myNS-Präfix enthält.

  • Die FOR XML-Direktiven XMLSCHEMA und XMLDATA können nicht zusammen mit der WITH XMLNAMESPACES-Klausel verwendet werden.

    CREATE TABLE T (x xml);
    GO
    WITH XMLNAMESPACES ('https://abc' as myNS )
    INSERT INTO T VALUES('<myNS:root/>');
    GO
    

Verwendung der XSINIL-Direktive

Wenn Sie die ELEMENTS XSINIL-Direktive verwenden, können Sie das xsi-Präfix nicht in der WITH XMLNAMESPACES-Klausel definieren. Es wird stattdessen automatisch hinzugefügt, wenn Sie ELEMENTS XSINIL verwenden. Die folgende Abfrage verwendet ELEMENTS XSINIL, die elementzentriertes XML generiert, wo Elementen, deren xsi:nil -Attribut auf TRUE festgelegt ist, Nullwerte zugeordnet werden.

WITH XMLNAMESPACES ('uri' as ns1)
SELECT ProductID as 'ns1:ProductID',
       Name      as 'ns1:Name',
       Color     as 'ns1:Color'
FROM Production.Product
WHERE ProductID = 316
FOR XML RAW, ELEMENTS XSINIL;

Dies ist das Ergebnis:

<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="uri">
  <ns1:ProductID>316</ns1:ProductID>
  <ns1:Name>Blade</ns1:Name>
  <ns1:Color xsi:nil="true" />
</row>

Angabe von Standard-Namespaces

Statt ein Namespacepräfix zu deklarieren, können Sie mit dem DEFAULT-Schlüsselwort einen Standardnamespace deklarieren. In der FOR XML-Abfrage wird der Standardnamespace mit den XML-Knoten des resultierenden XML verbunden. Im folgenden Beispiel definiert WITH XMLNAMESPACES zwei Namespacepräfixe, die gemeinsam über einen Standardnamespace definiert sind.

WITH XMLNAMESPACES ('uri1' as ns1,
                    'uri2' as ns2,
                    DEFAULT 'uri2')
SELECT ProductID,
      Name,
      Color
FROM Production.Product
WHERE ProductID IN (316, 317)
FOR XML RAW ('ns1:Product'), ROOT('ns2:root'), ELEMENTS;

Die FOR XML-Abfrage generiert elementzentriertes XML. Die Abfrage verwendet bei der Knotenbenennung beide Namespace-Präfixe. In der SELECT-Klausel legen ProductID, Name und Farbe keine Namen mit einem Präfix fest. Daher gehören die entsprechenden Elemente des resultierenden XML zum Standardnamespace.

<ns2:root xmlns="uri2" xmlns:ns2="uri2" xmlns:ns1="uri1">
  <ns1:Product>
    <ProductID>316</ProductID>
    <Name>Blade</Name>
  </ns1:Product>
  <ns1:Product>
    <ProductID>317</ProductID>
    <Name>LL Crankarm</Name>
    <Color>Black</Color>
  </ns1:Product>
</ns2:root>

Die folgende Abfrage ähnelt der vorherigen, allerdings ist der FOR XML AUTO-Modus festgelegt.

WITH XMLNAMESPACES ('uri1' as ns1,  'uri2' as ns2,DEFAULT 'uri2')
SELECT ProductID,
      Name,
      Color
FROM Production.Product as "ns1:Product"
WHERE ProductID IN (316, 317)
FOR XML AUTO, ROOT('ns2:root'), ELEMENTS;

Verwendung vordefinierter Namespaces

Wenn Sie vordefinierte Namespaces verwenden, müssen Sie (mit Ausnahme von xml-Namespace und xsi-Namespace, wenn ELEMENTS XSINIL verwendet wird) die Namespacebindung mit WITH XMLNAMESPACES explizit festlegen. Die folgende Abfrage definiert explizit den Namespacepräfix für die URI-Bindung für den vordefinierten Namespace (urn:schemas-microsoft-com:xml-sql).

WITH XMLNAMESPACES ('urn:schemas-microsoft-com:xml-sql' as sql)
SELECT 'SELECT * FROM Customers FOR XML AUTO, ROOT("a")' AS "sql:query"
FOR XML PATH('sql:root');

Dies ist das Ergebnis. SQLXML-Benutzer kennen diese XML-Vorlage. Weitere Informationen finden Sie unter SQLXML 4.0-Programmierkonzepte.

<sql:root xmlns:sql="urn:schemas-microsoft-com:xml-sql">
  <sql:query>SELECT * FROM Customers FOR XML AUTO, ROOT("a")</sql:query>
</sql:root>

Nur das xml-Namespacepräfix kann verwendet werden ohne explizit in WITH XMLNAMESPACES definiert zu sein, was die folgende Abfrage im PATH-Modus zeigt. Wenn das Präfix deklariert wird, muss es außerdem mit dem Namespace http://www.w3.org/XML/1998/namespace verbunden werden. Die in der SELECT-Klausel festgelegten Namen verweisen auf das xml-Namespacepräfix, das nicht explizit mit WITH XMLNAMESPACES definiert ist.

SELECT 'en'    as "English/@xml:lang",
       'food'  as "English",
       'ger'   as "German/@xml:lang",
       'Essen' as "German"
FOR XML PATH ('Translation');
GO

Die @xml:lang-Attribute verwenden den vordefinierten XML-Namespace. Da in XML Version 1.0 keine explizite Deklaration der xml-Namespacebindung notwendig ist, enthält das Ergebnis keine explizite Deklaration der Namespacebindung.

Dies ist das Ergebnis:

<Translation>
  <English xml:lang="en">food</English>
  <German xml:lang="ger">Essen</German>
</Translation>

Verwendung von WITH XMLNAMESPACES mit den xml-Datentypmethoden

Die xml-Datentyp-Methoden, die in einer SELECT-Abfrage oder, wenn es sich um die Methode modify() handelt, in UPDATE angegeben sind, müssen die Namespace-Deklaration in ihrem Prolog wiederholen. Dies kann einige Zeit in Anspruch nehmen. Die folgende Abfrage ruft beispielsweise Produktmodell-IDs ab, deren Katalogbeschreibungen eine Spezifikation enthalten. Dies geschieht, wenn das Element <Specifications> vorhanden ist.

SELECT ProductModelID, CatalogDescription.query('
declare namespace pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
    <Product
        ProductModelID= "{ sql:column("ProductModelID") }"
        />
') AS Result
FROM Production.ProductModel
WHERE CatalogDescription.exist('
    declare namespace  pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
     /pd:ProductDescription[(pd:Specifications)]'
    ) = 1;

In der vorherigen Abfrage deklarieren die Methoden query() und exist() in ihrem Prolog denselben Namespace. Zum Beispiel:

declare namespace pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";

Alternativ können Sie zuerst WITH XMLNAMESPACES deklarieren und in der Abfrage dann die Namespacepräfixe verwenden. In diesem Fall enthalten die Methoden query() und exist() im Prolog keine Namespace-Deklaration.

WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription' as pd)
SELECT ProductModelID, CatalogDescription.query('
    <Product
        ProductModelID= "{ sql:column("ProductModelID") }"
        />
') AS Result
FROM Production.ProductModel
WHERE CatalogDescription.exist('
     /pd:ProductDescription[(pd:Specifications)]'
    ) = 1;
GO

Eine explizite Deklaration im XQuery-Prolog überschreibt das in der WITH-Klausel definierte Namespace-Präfix und den Standardelement-Namespace.

Siehe auch