Dela via


Lägga till namnområden i frågor med HJÄLP av XMLNAMESPACES

gäller för:SQL ServerAzure SQL DatabaseAzure SQL Managed Instance

MED XMLNAMESPACES (Transact-SQL) ger stöd för namnområdes-URI på följande sätt:

Använd MED XMLNAMESPACES i FOR XML-frågor

MED XMLNAMESPACES kan du inkludera XML-namnområden i FOR XML-frågor. Tänk till exempel på följande FOR XML-fråga:

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

Det här är resultatet:

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

Om du vill lägga till namnområden i XML-koden som skapats av FOR XML-frågan anger du först namnområdesprefixet till URI-mappningar med hjälp av WITH NAMESPACES-satsen. Använd sedan namnområdesprefixen för att ange namnen i frågan enligt följande ändrade fråga. WITH XMLNAMESPACES-satsen anger namnområdesprefixet (ns1) till URI-mappning (uri) . Prefixet ns1 används sedan för att ange element- och attributnamn som ska konstrueras av FOR XML-frågan.

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;

XML-resultatet innehåller namnområdesprefixen:

<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öljande gäller för WITH XMLNAMESPACES-satsen:

  • Det stöds endast i RAW-, AUTO- och PATH-lägena för FOR XML-frågorna. EXPLICIT-läget stöds inte.

  • Det påverkar bara namnområdesprefixen för FOR XML-frågor och xml- datatypsmetoder, men inte XML-parsern. Följande fråga returnerar till exempel ett fel eftersom XML-dokumentet inte har någon namnområdesdeklaration för myNS-prefixet.

  • FOR XML-direktiven: XMLSCHEMA och XMLDATA kan inte användas när en WITH XMLNAMESPACES-sats är i bruk.

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

Använda XSINIL-direktivet

Du kan inte definiera xsi-prefixet i WITH XMLNAMESPACES-satsen om du använder ELEMENT XSINIL-direktivet. I stället läggs den till automatiskt när du använder ELEMENT XSINIL. I följande fråga används ELEMENT XSINIL som genererar elementcentrerad XML där null-värden mappas till element som har attributet xsi:nil inställt på Sant.

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;

Det här är resultatet:

<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>

Ange standardnamnområden

I stället för att deklarera ett namnområdesprefix kan du deklarera ett standardnamnområde med hjälp av nyckelordet DEFAULT. I FOR XML-frågan binder den standardnamnområdet till XML-noder i den resulterande XML-koden. I följande exempel definierar WITH XMLNAMESPACES två namnområdesprefix som definieras tillsammans med ett standardnamnområde.

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;

FOR XML-frågan genererar elementcentrerad XML. Frågan använder båda namnområdesprefixen i namngivningsnoder. I SELECT-satsen anger ProductID, Namn och Färg inte ett namn med något prefix. Därför tillhör motsvarande element i den resulterande XML-koden standardnamnområdet.

<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>

Följande fråga liknar den föregående, förutom att AUTO-läget FÖR XML har angetts.

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;

Använda fördefinierade namnområden

När du använder fördefinierade namnområden, förutom xml-namnområdet och xsi-namnområdet när ELEMENT XSINIL används, måste du uttryckligen ange namnområdesbindningen med hjälp av WITH XMLNAMESPACES. Följande fråga definierar explicit namnområdesprefixet till URI-bindningen för det fördefinierade namnområdet (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');

Det här är resultatet. SQLXML-användare är bekanta med den här XML-mallen. Mer information finns i SQLXML 4.0 Programming Concepts.

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

Endast xml-namnområdesprefixet kan användas utan att uttryckligen definiera det i WITH XMLNAMESPACES, som du ser i följande PATH-lägesfråga. Om prefixet deklareras måste det också vara bundet till namnområdet http://www.w3.org/XML/1998/namespace. Namnen som anges i SELECT-satsen refererar till xml-namnområdesprefixet som inte uttryckligen definieras med hjälp av WITH XMLNAMESPACES.

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

Attributen @xml:lang använder det fördefinierade XML-namnområdet. Eftersom XML-version 1.0 inte kräver den explicita deklarationen av xml-namnområdesbindningen innehåller resultatet inte någon explicit deklaration av namnområdesbindningen.

Det här är resultatet:

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

Använd WITH XMLNAMESPACES med xml-datatypsmetoderna

De xml-datatypsmetoder som anges i en SELECT-fråga, eller i UPDATE när det är modify()-metoden, måste alla upprepa namnområdesdeklarationen i sin prolog. Det kan vara tidskrävande. Följande fråga hämtar till exempel produktmodell-ID:t vars katalogbeskrivningar innehåller specifikation. Det vill säga, <Specifications>-elementet finns.

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;

I föregående fråga deklarerar både metoderna query() och exist() samma namnområde i sin prolog. Till exempel:

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

Du kan också deklarera MED XMLNAMESPACES först och använda namnområdesprefixen i frågan. I det här fallet behöver query()- och exist()-metoderna inte inkludera namnområdesdeklarationer i sin prolog.

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

En explicit deklaration i XQuery-prolog åsidosätter namnområdesprefixet och standardelementets namnområde som definieras i WITH-satsen.

Se även