Megosztás:


XML-konstrukció (XQuery)

A következőkre vonatkozik:SQL Server

Az XQueryben a közvetlen és kiszámított konstruktorokkal hozhat létre XML-struktúrákat egy lekérdezésen belül.

Jegyzet

A közvetlen és a számított konstruktorok között nincs különbség.

Közvetlen konstruktorok használata

Ha közvetlen konstruktorokat használ, xml-szerű szintaxist kell megadnia az XML létrehozásakor. Az alábbi példák a közvetlen konstruktorok XML-felépítését szemléltetik.

Elemek létrehozása

XML-jelölések használatával elemeket hozhat létre. Az alábbi példa a közvetlen elem konstruktorkifejezését használja, és létrehoz egy <ProductModel> elemet. A létrehozott elem három gyermekelemből áll

  • Szövegcsomópont.

  • Két elemcsomópont és <Summary><Features>.

    • Az <Summary> elem egy olyan szövegcsomópont-gyermekvel rendelkezik, amelynek értéke ."Some description"

    • Az <Features> elem három elemcsomópontból áll, <Color><Weight>és <Warranty>. Ezen csomópontok mindegyike egy szöveges csomópont gyermekével rendelkezik, 252 years parts and laborés az értékekkel Redrendelkezik.

DECLARE @x AS XML;

SET @x = '';

SELECT @x.query('<ProductModel ProductModelID="111">;
This is product model catalog description.
<Summary>Some description</Summary>
<Features>
  <Color>Red</Color>
  <Weight>25</Weight>
  <Warranty>2 years parts and labor</Warranty>
</Features></ProductModel>');

Az eredményként kapott XML:

<ProductModel ProductModelID="111">
  This is product model catalog description.
  <Summary>Some description</Summary>
  <Features>
    <Color>Red</Color>
    <Weight>25</Weight>
    <Warranty>2 years parts and labor</Warranty>
  </Features>
</ProductModel>

Bár az elemek konstans kifejezésekből való létrehozása hasznos, ahogy az ebben a példában is látható, az XQuery nyelvi funkció valódi előnye az, hogy olyan XML-t hozhat létre, amely dinamikusan kinyeri az adatokat egy adatbázisból. A lekérdezési kifejezések kapcsos zárójelekkel határozhatók meg. Az eredményként kapott XML-fájlban a kifejezést az értéke váltja fel. Az alábbi lekérdezés például egy elemet hoz létre egy <NewRoot> gyermekelemmel (<e>). Az elem <e> értékét úgy számítjuk ki, hogy egy görbekifejezést ad meg a kapcsos zárójelek között ("{ ... }").

DECLARE @x AS XML;

SET @x = '<root>5</root>';

SELECT @x.query('<NewRoot><e> { /root } </e></NewRoot>');

A kapcsos zárójelek környezetváltó jogkivonatokként működnek, és a lekérdezést XML-konstrukcióról lekérdezés-kiértékelőre váltják. Ebben az esetben a kapcsos zárójelen belüli XQuery-elérési út kifejezés (/root) kiértékelése és az eredmények helyettesítése történik.

Az eredmény a következő:

<NewRoot>
  <e>
    <root>5</root>
  </e>
</NewRoot>

Az alábbi lekérdezés az előzőhöz hasonló. A kapcsos zárójelek kifejezése azonban megadja az data() elem atomi értékének lekéréséhez <root> és a létrehozott elemhez való hozzárendeléséhez tartozó függvényt. <e>

DECLARE @x AS XML;
SET @x = '<root>5</root>';

DECLARE @y AS XML;
SET @y = (SELECT @x.query('
                           <NewRoot>
                             <e> { data(/root) } </e>
                           </NewRoot>'));

SELECT @y;

Az eredmény a következő:

<NewRoot>
  <e>5</e>
</NewRoot>

Ha a szöveg részeként szeretné használni a kapcsos zárójeleket a környezetváltási jogkivonatok helyett, azokat "}}" vagy "{{" néven is feloldhatja, ahogyan az ebben a példában látható:

DECLARE @x AS XML;
SET @x = '<root>5</root>';

DECLARE @y AS XML;
SET @y = (SELECT @x.query('
<NewRoot> Hello, I can use {{ and  }} as part of my text</NewRoot>'));

SELECT @y;

Az eredmény a következő:

<NewRoot> Hello, I can use { and  } as part of my text</NewRoot>

Az alábbi lekérdezés egy másik példa az elemek közvetlen elemkonstruktor használatával történő létrehozására. Emellett az elem értékét a <FirstLocation> kifejezés kapcsos zárójelekben való végrehajtásával nyeri ki. A lekérdezési kifejezés a Production.ProductModel tábla Utasítások oszlopából adja vissza a gyártási lépéseket az első műhelyhelyen.

SELECT Instructions.query('
    declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
        <FirstLocation>
           { /AWMI:root/AWMI:Location[1]/AWMI:step }
        </FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;

Az eredmény a következő:

<FirstLocation>
  <AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">
      Insert <AWMI:material>aluminum sheet MS-2341</AWMI:material> into the <AWMI:tool>T-85A framing tool</AWMI:tool>.
  </AWMI:step>
  <AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">
      Attach <AWMI:tool>Trim Jig TJ-26</AWMI:tool> to the upper and lower right corners of the aluminum sheet.
  </AWMI:step>
   ...
</FirstLocation>

Elemtartalom XML-konstrukcióban

Az alábbi példa a kifejezések viselkedését szemlélteti az elemtartalom közvetlen elemkonstruktor használatával történő létrehozásában. Az alábbi példában a közvetlen elemkonstruktor egy kifejezést határoz meg. Ebben a kifejezésben egy szöveges csomópont jön létre az eredményként kapott XML-fájlban.

DECLARE @x AS XML;
SET @x = '
<root>
  <step>This is step 1</step>
  <step>This is step 2</step>
  <step>This is step 3</step>
</root>';

SELECT @x.query('
<result>
 { for $i in /root[1]/step
    return string($i)
 }
</result>');

A kifejezéskiértékelésből eredő atomérték-sorozat hozzáadódik a szövegcsomóponthoz, és a szomszédos atomértékek között szóköz van hozzáadva, ahogy az az eredményben is látható. A létrehozott elemnek egy gyermeke van. Ez egy szöveges csomópont, amely az eredményben megjelenített értéket tartalmazza.

<result>This is step 1 This is step 2 This is step 3</result>

Ha egy kifejezés helyett három külön kifejezést ad meg, amelyek három szövegcsomópontot hoznak létre, a szomszédos szövegcsomópontok egyetlen szövegcsomópontba egyesülnek összefűzéssel az eredményül kapott XML-fájlban.

DECLARE @x AS XML;
SET @x = '
<root>
  <step>This is step 1</step>
  <step>This is step 2</step>
  <step>This is step 3</step>
</root>';

SELECT @x.query('
<result>
 { string(/root[1]/step[1]) }
 { string(/root[1]/step[2]) }
 { string(/root[1]/step[3]) }
</result>');

A létrehozott elemcsomópontnak egy gyermeke van. Ez egy szöveges csomópont, amely az eredményben megjelenített értéket tartalmazza.

<result>This is step 1This is step 2This is step 3</result>

Attribútumok létrehozása

Ha a közvetlen elemkonstruktor használatával hoz létre elemeket, xml-szerű szintaxissal is megadhatja az elem attribútumait, ahogyan az ebben a példában látható:

DECLARE @x AS XML;
SET @x = '';

SELECT @x.query('<ProductModel ProductModelID="111">;
This is product model catalog description.
<Summary>Some description</Summary>
</ProductModel>');

Az eredményként kapott XML:

<ProductModel ProductModelID="111">
  This is product model catalog description.
  <Summary>Some description</Summary>
</ProductModel>

A létrehozott elem <ProductModel> egy ProductModelID attribútummal és a következő gyermekcsomópontokkal rendelkezik:

  • Szövegcsomópont, This is product model catalog description.

  • Elemcsomópont, <Summary>. Ennek a csomópontnak egy szöveges csomópontja van, Some description.

Attribútum létrehozásakor az értékét kapcsos zárójelben lévő kifejezéssel adhatja meg. Ebben az esetben a kifejezés eredménye attribútumértékként lesz visszaadva.

Az alábbi példában a data() függvény nem feltétlenül szükséges. Mivel egy attribútumhoz rendeli hozzá a kifejezés értékét, data() a program implicit módon alkalmazza a megadott kifejezés beírt értékének lekérésére.

DECLARE @x AS XML;
SET @x = '<root>5</root>';

DECLARE @y AS XML;
SET @y = (SELECT @x.query('<NewRoot attr="{ data(/root) }" ></NewRoot>'));

SELECT @y;

Az eredmény a következő:

<NewRoot attr="5" />

Az alábbiakban egy másik példát mutatunk be, amelyben a LocationID és a SetupHrs attribútum felépítéséhez kifejezések vannak megadva. Ezeket a kifejezéseket az Utasítás oszlop XML-fájlja alapján értékeli ki a rendszer. A kifejezés begépelt értéke az attribútumokhoz van rendelve.

SELECT Instructions.query('
    declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
        <FirstLocation
         LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
         SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
           { /AWMI:root/AWMI:Location[1]/AWMI:step }
        </FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;

A részleges eredmény a következő:

<FirstLocation LocationID="10" SetupHours="0.5" >
  <AWMI:step ...
  </AWMI:step>
  ...
</FirstLocation>

Megvalósítási korlátozások

Ezek a korlátozások:

  • Több vagy vegyes (sztring- és XQuery-kifejezés) attribútumkifejezés nem támogatott. Az alábbi lekérdezésben látható módon például olyan XML-t kell létrehoznia, amelyben Item állandó, és a 5 érték egy lekérdezési kifejezés kiértékelésével nyerhető le:

    <a attr="Item 5" />
    

    A következő lekérdezés hibát ad vissza, mert konstans sztringet kever egy kifejezéssel ({/x}), és ez nem támogatott:

    DECLARE @x AS XML;
    SET @x = '<x>5</x>';
    
    SELECT @x.query('<a attr="Item {/x}"/>');
    

    Ebben az esetben a következő lehetőségek közül választhat:

    • Adja meg az attribútum értékét két atomérték összefűzésével. Ezek az atomi értékek az attribútumértékek közé vannak szerializálva, az atomértékek között szóközzel:

      SELECT @x.query('<a attr="{''Item'', data(/x)}"/>');
      

      Az eredmény a következő:

      <a attr="Item 5" />
      
    • A összefűző függvény a két sztringargumentum összefűzésével az eredményül kapott attribútumértékbe:

      SELECT @x.query('<a attr="{concat(''Item'', /x[1])}"/>');
      

      Ebben az esetben nincs térköz a két sztringérték között. Ha szóközt szeretne a két érték között, explicit módon kell megadnia.

      Az eredmény a következő:

      <a attr="Item5" />
      
  • Több kifejezés attribútumértékként nem támogatott. A következő lekérdezés például hibát ad vissza:

    DECLARE @x AS XML;
    SET @x = '<x>5</x>';
    
    SELECT @x.query('<a attr="{/x}{/x}"/>');
    
  • A heterogén sorozatok nem támogatottak. Ha egy heterogén szekvenciát attribútumértékként próbál hozzárendelni, hibát ad vissza, ahogyan az alábbi példában is látható. Ebben a példában egy heterogén sorozat, egy "Item" sztring és egy elem <x>van megadva attribútumértékként:

    DECLARE @x AS XML;
    SET @x = '<x>5</x>';
    
    SELECT @x.query('<a attr="{''Item'', /x }" />');
    

    Ha alkalmazza a data() függvényt, a lekérdezés azért működik, mert lekéri a kifejezés atomi értékét, /xamelyet a sztring összefűz. Az alábbiakban az atomértékek sorozata található:

    SELECT @x.query('<a attr="{''Item'', data(/x)}"/>');
    

    Az eredmény a következő:

    <a attr="Item 5" />
    
  • Az attribútumcsomópont sorrendje a szerializálás során, nem pedig a statikus típusellenőrzés során lesz kényszerítve. A következő lekérdezés például meghiúsul, mert attribútumot próbál hozzáadni egy nem attribútumalapú csomópont után.

    SELECT CONVERT (XML, '').query('
        element x { attribute att { "pass" }, element y { "Element text" }, attribute att2 { "fail" } }
        ');
    GO
    

    Az előző lekérdezés a következő hibát adja vissza:

    XML well-formedness check: Attribute cannot appear outside of element declaration. Rewrite your XQuery so it returns well-formed XML.
    

Névterek hozzáadása

Ha az XML-t közvetlen konstruktorokkal hozza létre, a létrehozott elem és attribútumnevek névtérelőtaggal minősíthetők. Az előtagot a következő módokon kötheti a névtérhez:

  • Névtér deklarálási attribútum használatával.
  • A záradék használatával WITH XMLNAMESPACES .
  • Az XQuery prologban.

Névtér deklarálási attribútum használata névterek hozzáadásához

Az alábbi példa egy névtér deklarációs attribútumot használ az elem <a> felépítésében egy alapértelmezett névtér deklarálásához. A gyermekelem <b> felépítése visszavonja a szülőelemben deklarált alapértelmezett névtér deklarációját.

DECLARE @x AS XML;
SET @x = '<x>5</x>';

SELECT @x.query('
  <a xmlns="a">
    <b xmlns=""/>
  </a>');

Az eredmény a következő:

<a xmlns="a">
  <b xmlns="" />
</a>

Előtagot rendelhet a névtérhez. Az előtag az elem <a>felépítésében van megadva.

DECLARE @x AS XML;
SET @x = '<x>5</x>';

SELECT @x.query('
  <x:a xmlns:x="a">
    <b/>
  </x:a>');

Az eredmény a következő:

<x:a xmlns:x="a">
  <b />
</x:a>

Az XML-konstrukcióban nem deklarálhat alapértelmezett névteret, de névtérelőtagot nem deklarálhat. A következő lekérdezés hibát ad vissza, mert az elem <b>felépítésében megadott előtag nem deklarálható.

DECLARE @x AS XML;
SET @x = '<x>5</x>';

SELECT @x.query('
  <x:a xmlns:x="a">
    <b xmlns:x=""/>
  </x:a>');

Az újonnan létrehozott névtér a lekérdezésen belül használható. Az alábbi lekérdezés például egy névteret deklarál az elem létrehozásakor, <FirstLocation>és megadja a LocationID és a SetupHrs attribútum értékeinek kifejezéseiben szereplő előtagot.

SELECT Instructions.query('
        <FirstLocation xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
         LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
         SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
           { /AWMI:root/AWMI:Location[1]/AWMI:step }
        </FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;

Az új névtérelőtag ilyen módon történő létrehozása felülírja az előtaghoz tartozó, már meglévő névtér-deklarációt. A névtér deklarációja például felülírja a lekérdezés prologjában lévő névtérdeklarációt AWMI="https://someURI"az <FirstLocation> elemben.

SELECT Instructions.query('
declare namespace AWMI="https://someURI";
        <FirstLocation xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
         LocationID="{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
         SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
           { /AWMI:root/AWMI:Location[1]/AWMI:step }
        </FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;

Névterek hozzáadása prolog használatával

Ez a példa bemutatja, hogyan lehet névtereket hozzáadni a létrehozott XML-hez. A lekérdezési prologban egy alapértelmezett névtér van deklarálva.

DECLARE @x AS XML;
SET @x = '<x>5</x>';

SELECT @x.query('
           declare default element namespace "a";
            <a><b xmlns=""/></a>');

Az elem <b>felépítésében a névtér deklarálási attribútuma üres sztringgel van megadva értékként. Ez nem deklarálja a szülőben deklarált alapértelmezett névteret.

Az eredmény a következő:

<a xmlns="a">
  <b xmlns="" />
</a>

XML-építés és térközkezelés

Az XML-konstrukció elemtartalma tartalmazhat szóköz karaktereket. Ezeket a karaktereket a következő módokon kezeli a rendszer:

  • A névtér URI-jaiban a szóköz karaktereket XSD-típusként kezeli a rendszer anyURI. Pontosabban a következő módon történik a kezelésük:

    • A rendszer levágja a kezdő és a végén lévő szóköz karaktereket.
    • A belső szóköz karakterértékek egyetlen térbe vannak összecsukva
  • Az attribútum tartalmának vonalas karaktereit szóközök váltják fel. Az összes többi szóköz karakter változatlan marad.

  • A fehér tér az elemeken belül megmarad.

Az alábbi példa az XML-konstrukcióban végzett szabad területkezelést szemlélteti:

-- line feed is replaced by space.
DECLARE @x AS XML;
SET @x = '';

SELECT @x.query('

declare namespace myNS="   https://
 abc/
xyz

";
<test attr="    my
test   attr
value    " >

<a>

This     is  a

test

</a>
</test>
') AS XML_Result;

Az eredmény a következő:

-- result
<test attr="<test attr="    my test   attr  value    "><a>

This     is  a

test

</a></test>
"><a>

This     is  a

test

</a></test>

Egyéb közvetlen XML-konstruktorok

Az utasítások és XML-megjegyzések feldolgozására szolgáló konstruktorok ugyanazt a szintaxist használják, mint a megfelelő XML-szerkezet szintaxisát. A szöveges csomópontok számítási konstruktorai szintén támogatottak, de elsősorban szövegcsomópontok létrehozásához használhatók XML DML .

Jegyzet

Az explicit szövegcsomópont konstruktorának használatára vonatkozó példát a beszúrásban (XML DML) szereplő konkrét példában találhatja meg.

A következő lekérdezésben a létrehozott XML tartalmaz egy elemet, két attribútumot, egy megjegyzést és egy feldolgozási utasítást. A rendszer vesszőt használ a <FirstLocation>folyamat előtt, mert egy sorozat készül.

SELECT Instructions.query('
  declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
   <?myProcessingInstr abc="value" ?>,
   <FirstLocation
        WorkCtrID = "{ (/AWMI:root/AWMI:Location[1]/@LocationID)[1] }"
        SetupHrs = "{ (/AWMI:root/AWMI:Location[1]/@SetupHours)[1] }" >
       <!-- some comment -->
       <?myPI some processing instructions ?>
       { (/AWMI:root/AWMI:Location[1]/AWMI:step) }
    </FirstLocation>
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;

A részleges eredmény a következő:

<?myProcessingInstr abc="value" ?>
<FirstLocation WorkCtrID="10" SetupHrs="0.5">
  <!-- some comment -->
  <?myPI some processing instructions ?>
  <AWMI:step xmlns:AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions">I
  nsert <AWMI:material>aluminum sheet MS-2341</AWMI:material> into the <AWMI:tool>T-85A framing tool</AWMI:tool>.
  </AWMI:step>
    ...
</FirstLocation>

Számított konstruktorok használata

Ebben az esetben meg kell adnia azokat a kulcsszavakat, amelyek azonosítják a létrehozni kívánt csomópont típusát. Csak a következő kulcsszavak támogatottak:

  • elem
  • attribútum
  • SMS

Az elem- és attribútumcsomópontok esetében ezeket a kulcsszavakat a csomópont neve és a kapcsos zárójelek közé foglalt kifejezés követi, amely létrehozza az adott csomópont tartalmát. Az alábbi példában ezt az XML-t hozza létre:

<root>
  <ProductModel PID="5">Some text <summary>Some Summary</summary></ProductModel>
</root>

A számított konstruktorokat használó lekérdezés az XML-t hozza létre:

DECLARE @x AS XML;
SET @x = '';

SELECT @x.query('element root
               {
                  element ProductModel
     {
attribute PID { 5 },
text{"Some text "},
    element summary { "Some Summary" }
 }
               } ');

A csomópont tartalmát létrehozó kifejezés megadhat egy lekérdezési kifejezést.

DECLARE @x AS XML;
SET @x = '<a attr="5"><b>some summary</b></a>';

SELECT @x.query('element root
               {
                  element ProductModel
     {
attribute PID { /a/@attr },
text{"Some text "},
    element summary { /a/b }
 }
               } ');

Az XQuery specifikációjában meghatározott számított elem és attribútumkonstruktorok lehetővé teszik a csomópontnevek kiszámítását. Ha közvetlen konstruktorokat használ az SQL Serverben, a csomópontneveket, például az elemet és az attribútumot állandó literálként kell megadni. Ezért az elemek és attribútumok közvetlen konstruktoraiban és számított konstruktoraiban nincs különbség.

Az alábbi példában a létrehozott csomópontok tartalma a ProductModel tábla XML- adattípusának Utasítások oszlopában tárolt XML-gyártási utasításokból származik.

SELECT Instructions.query('
  declare namespace AWMI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
   element FirstLocation
     {
        attribute LocationID { (/AWMI:root/AWMI:Location[1]/@LocationID)[1] },
        element   AllTheSteps { /AWMI:root/AWMI:Location[1]/AWMI:step }
     }
') AS Result
FROM Production.ProductModel
WHERE ProductModelID = 7;

A részleges eredmény a következő:

<FirstLocation LocationID="10">
  <AllTheSteps>
    <AWMI:step> ... </AWMI:step>
    <AWMI:step> ... </AWMI:step>
    ...
  </AllTheSteps>
</FirstLocation>

Egyéb megvalósítási korlátozások

A számított attribútumkonstruktorok nem használhatók új névtér deklarálásához. Az SQL Server nem támogatja a következő számított konstruktorokat is:

  • Számítási dokumentumcsomópont konstruktorai
  • Számítási feldolgozási utasítás konstruktorai
  • Számított megjegyzéskonstruktorok
  • XQuery-kifejezések