Bazy danych

XML w relacyjnych bazach danych

  • 2012-09-04 19:35
  • 0 komentarzy
  • 2386 odsłon
  • Oceń ten tekst jako pierwszy
Pierwszy opracowany przez firmę IBM język strukturalizowania dokumentów, był GML (Generalized Markup Language). Składnia tego standardu stopniowo ewoluowała, dostosowując się do rosnącego za potrzebowania na rozmaitą funkcjonalność. Rozwój ten zaowocował zdefiniowaniem w 1986 roku SGML-a jako normy ISO.
SGML to profesjonalnych system zarządzania dokumentami. Ze względu na udostępniane skomplikowane opcje uproszczono w 1998 roku wprowadzono uniwersalny język formalny przeznaczony  XML (Extensible Markup Language).  

W środowisku relacyjnych baz danych opisane wyżej uwarunkowania spowodowały potrzebę przetwarzania dokumentów XML. Wymagało to stworzenia możliwości realizowania trzech podstawowych operacji:
  • Przechowywanie dokumentów XML
  • Przekształcanie danych relacyjnych do postaci XML
  • Pobieranie danych z dokumentu XML.
Pierwsze funkcjonalności wspierające współpracę z dokumentów XML wprowadzono w MS SQL Server 2000 poprzez:
  • Funkcje OPENXML (konwertującą dokument XML do postaci tabeli relacyjnej)
  • Klauzule FOR XML w poleceniu SELECT (konwertującą wynik zapytania do postaci dokumentu XML)
Klauzule FOR XML obsługuje następujące tryby:
  • RAW
  • AUTO
  • EXPLICIT
  • PATH
Wymienione mechanizmy zostaną omówione na podstawie przykładów, przy zastosowaniu tabel:
[Tabela: Osoby2]

IdOsobyNazwiskoImieDataUrodzeniaCzyKobietaPeselIdMiastaZnacznikplecwieknic
45KotJanina1985-07-2918507291198610x00000000000007FDKobieta27NULL
46KotJan1983-03-1218303123450120x00000000000007FEKobieta29NULL
47KretZosia1983-03-1518303153458120x00000000000007FFKobieta29NULL
74PiasekZosia1987-04-2918704294536780x000000000000081EKobieta25NULL
75PiasekZosia1987-04-2918704294536780x000000000000081FKobieta25NULL
76PiasekZosia1987-04-2918704294536780x0000000000000820Kobieta25NULL
77PiasekZosia1987-04-2918704294536780x0000000000000821Kobieta25NULL
79ZajacHelena1977-09-0917709093456710x0000000000000823Kobieta35NULL
81ZaajacHelena1977-09-0917709093456720x0000000000000825Kobieta35NULL
82KrolikJan1988-08-0808808083455690x0000000000000826Mężczyzna24NULL
83KrolikJan1988-08-0808808083455690x0000000000000827Mężczyzna24NULL
84JenotJanina1988-08-08188080834546100x0000000000000828Kobieta24NULL


[Tabela: Miasta]

IdMiastaNazwa
2Dęblin
6Kielce
9Kolobrzeg
10Lublin
8nowe miasto nad Pilica
4Opole
3Sopot
1Warszawa


[Tabela: kategorie]

idhigher_idNameSequence
10Samochod1
20Kemping2
31Fiat1
41Skoda2
732
51Audi3
62Krotka1


[Tabela: Klasy]

idklasyNazwaRokSzkolnycos
1Ia2011/2012sshhhdgguu
2IIa2011/2012sshhhdgguu
3IIc2011/2012sshhhdgguu
4IVb2011/2012sshhhdgguu
5IId2011/2012sshhhdgguu
6Va2011/2012sshhhdgguu
13Ic2011/2012sshhhdgguu
14VIa2011/2012sshhhdgguu
15VIa2011/2012sshhhdgguu
16Vb2011/2012sshhhdgguu
18Vc2011/2012sshhhdgguu
20Vd2012/2012sshhhdgguu
21Ve2012/2012sshhhdgguu
22Vf2012/2012sshhhdgguu
23Vg2012/2012sshhhdgguu
24IIe2012/2012sshhhdgguu


[Tabela: Uczniowie]

iduczniaNazwiskoImieDataUrodzeniaCzyChlopakPeselidklasy
1InnyGośćNULL1410-07-140100714511472
3GazelaBasia1992-02-220920222776542
4KurkaJola1992-06-020920602887882
5GąskaWacek1991-03-111910311991231
6KrówkaRysio1992-05-151920515776461
7ZebraWojtek1993-03-131930303998461
8GazelaBasia1992-11-110921111774462
9SarenkaRysio1992-12-120921212787663
10KonikKasia1993-03-120930312754462
11RybaJan1993-05-151930515877462
12KuraKasia1993-02-220930222776542
13ŁośJola1993-06-020930602887882
14MiśWacek1993-03-111930311991234
15OkońRysio1993-05-151930515776464
16PłotkaWojtek1993-03-131930303998462
17RóżyczkaBasia1993-11-110931111774462
18StokrotkaRysio1993-12-120931212787662
19WilczekJasio1999-12-120991212098763


RAW
Użycie jednego z podstawowych trybów znajduje się w poniższym przykładzie.
Przykład 1)
SELECT TOP 3 Nazwisko,
Imie,
CASE CzyKobieta
   WHEN 0 THEN 'Mężczyzna'
ELSE 'Kobieta'
END AS Plec 
FROM Osoby2
FOR XML RAW

Wynik zapytania wygenerował jedną kolumnę z jednym wierszem. Jako odnośnik do dokumentu XML. Po kliknięciu zostaje otwarte nowe okno z danymi umieszczonymi w atrybutach. Należy zwrócić uwagę, że nie pojawił się element główny, jedynie rekordy zostały objęte w znaczniku row jako atrybuty.
<row Nazwisko="Kot" Imie="Janina" Plec="Kobieta" />
<row Nazwisko="Kot" Imie="Jan" Plec="Kobieta" />
<row Nazwisko="Kret" Imie="Zosia" Plec="Kobieta" />


Przykład 2)
Do trybu RAW można zdefiniować parametr, a także zdefiniowanie znacznika głównego korzystając z opcji ROOT . Drugi przykład przedstawiła te mechanizmy:
SELECT TOP 3 Nazwisko,
Imie,
CASE CzyKobieta
        WHEN 0 THEN 'Mężczyzna'
        ELSE 'Kobieta'
        END AS Plec 
FROM Osoby2
FOR XML RAW('osoba') , ROOT

Ponownie zostaje wygenerowana kolumna z jednym polem, jako odnośnik do dokumentu. W momencie jego użycia tak, jak w poprzednim przykładzie otwiera się nowe okno. Gdzie
wynik wygenerował dodatkowo znacznik główny jako <root> , zwrócony dokument XML jest poprawnie sformułowany. Wprowadzony parametr do trybu RAW('osoba') modyfikuje nazwę znacznika w którym są wyświetlone rekordy pobrane z tabeli:
<root>
  <osoba Nazwisko="Kot" Imie="Janina" Plec="Kobieta" />
  <osoba Nazwisko="Kot" Imie="Jan" Plec="Kobieta" />
  <osoba Nazwisko="Kret" Imie="Zosia" Plec="Kobieta" />
</root>


Przykład 3)
Dla ROOT można podać także z parametrem , do poniższego przykłądu również dopisano opcje ELEMENTS. Poższysze zapytanie SQL:
SELECT TOP 3 Nazwisko,
Imie,
CASE CzyKobieta
        WHEN 0 THEN 'Mężczyzna'
        ELSE 'Kobieta'
        END AS Plec 
FROM osoby
FOR XML RAW('osoba'), ROOT('ListaOsob'), ELEMENTS

Powyższe zapytanie SQL, zwraca określony znacznik główny <listaosob> . Zawarty w nim znacznik <osoba> zawiera zestawy elementów podrzędnych. Odpowiada za to opcja ELEMENTS powodująca, że zamiast atrybutów, do umieszczenia zawartości kolumn wykorzystane są elementy, które odpowiadają nazwom kolumn objętych instrukcją SQL. Wartości nie są już objęte jako atrybuty:
<ListaOsob>
  <osoba>
    <Nazwisko>Kot</Nazwisko>
    <Imie>Janina</Imie>
    <Plec>Kobieta</Plec>
  </osoba>
  <osoba>
    <Nazwisko>Kot</Nazwisko>
    <Imie>Jan</Imie>
    <Plec>Kobieta</Plec>
  </osoba>
  <osoba>
    <Nazwisko>Kret</Nazwisko>
    <Imie>Zosia</Imie>
    <Plec>Kobieta</Plec>
  </osoba>
</ListaOsob>


Przykład 4)
Korzystając z nowej tabeli kategorie w zapytaniu poniżej zmodyfikowano RAW('kategorie') , opcje ROOT('ListaKategorie') dodano również  ELEMENTS XSINIL ,  XMLSCHEMA :
SELECT id,
higher_id,
Name,
SEQUENCE
FROM kategorie
FOR XML RAW('kategorie'), ROOT('ListaKategorie'), ELEMENTS XSINIL,XMLSCHEMA

W momecie klikniecia w nowym oknie, powyższy przykład zawierający ELEMENTS XSINIL powoduje dodanie argumentu do gównego znacznika xmlns:xsi=http:www.w3.org/2001/XMLSchema-instance// Dla wartości zawierających NULL powoduje dodanie atrybutu  xsi: nil = "true" .
Zapytanie SQL posiada również, dyrekywę XMLSCHEMA , którą można wykonać jedynie dla trybów RAW lub AUTO. Dodanie do znaczników pseudo-atrybutów XML namespace, standardu służącego do definiowania struktury dokumentu XML. Deklaracja przestrzeni nazw ma następującą składnię:
xmlns: prefix = "URI".

Gdzie Uniform Resource Identifier (URI) to ciąg znaków, który identyfikuje zasob sieci Internet.

Kiedy przestrzeń nazw jest definiowana dla danego elementu, wszystkie elementy podrzędne z tego samego prefiksu związane są z tą samą przestrzenią nazw.
W powyższym przykładzie atrybut  xmlns w znaczniku  <kategorie>  posiada prefiksy xsd.

<ListaKategorie xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
    <xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
    <xsd:element name="kategorie">
      <xsd:complexType>
        <xsd:sequence>
          <xsd:element name="id" type="sqltypes:int" nillable="1" />
          <xsd:element name="higher_id" type="sqltypes:int" nillable="1" />
          <xsd:element name="Name" nillable="1">
            <xsd:simpleType>
              <xsd:restriction base="sqltypes:nchar" sqltypes:localeId="1045" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth">
                <xsd:maxLength value="10" />
              </xsd:restriction>
            </xsd:simpleType>
          </xsd:element>
          <xsd:element name="sequence" type="sqltypes:int" nillable="1" />
        </xsd:sequence>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <kategorie xmlns="urn:schemas-microsoft-com:sql:SqlRowSet2">
    <id>1</id>
    <higher_id>0</higher_id>
    <Name>Samochod  </Name>
    <sequence>1</sequence>
  </kategorie>
  <kategorie xmlns="urn:schemas-microsoft-com:sql:SqlRowSet2">
    <id>2</id>
    <higher_id>0</higher_id>
    <Name>Kemping   </Name>
    <sequence>2</sequence>
  </kategorie>
  <kategorie xmlns="urn:schemas-microsoft-com:sql:SqlRowSet2">
    <id>3</id>
    <higher_id>1</higher_id>
    <Name>Fiat      </Name>
    <sequence>1</sequence>
  </kategorie>
  <kategorie xmlns="urn:schemas-microsoft-com:sql:SqlRowSet2">
    <id>4</id>
    <higher_id>1</higher_id>
    <Name>Skoda     </Name>
    <sequence>2</sequence>
  </kategorie>
  <kategorie xmlns="urn:schemas-microsoft-com:sql:SqlRowSet2">
    <id>7</id>
    <higher_id>3</higher_id>
    <Name>          </Name>
    <sequence>2</sequence>
  </kategorie>
  <kategorie xmlns="urn:schemas-microsoft-com:sql:SqlRowSet2">
    <id>5</id>
    <higher_id>1</higher_id>
    <Name>Audi      </Name>
    <sequence>3</sequence>
  </kategorie>
  <kategorie xmlns="urn:schemas-microsoft-com:sql:SqlRowSet2">
    <id>6</id>
    <higher_id>2</higher_id>
    <Name>Krotka    </Name>
    <sequence>1</sequence>
  </kategorie>
</ListaKategorie>

Przykład 5)
Ostatnie zapytanie SQL zawiera dodatkowo dyrektywę z parametrem XMLSCHEMA('urn: XMLSCHEMA.com') :
SELECT id,
higher_id,
Name,
SEQUENCE
FROM kategorie
FOR XML RAW('kategorie'), ROOT('ListaKategorie'), ELEMENTS XSINIL, XMLSCHEMA('urn:XMLSCHEMA.pl')

Wynik zwraca odnośnik w postaci tabeli. Po uruchomieniu , utworzony dokument XML przedstawiła się następująco:
<ListaKategorie xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <xsd:schema targetNamespace="urn:XMLSCHEMA.pl" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
    <xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
    <xsd:element name="kategorie">
      <xsd:complexType>
        <xsd:sequence>
          <xsd:element name="id" type="sqltypes:int" nillable="1" />
          <xsd:element name="higher_id" type="sqltypes:int" nillable="1" />
          <xsd:element name="Name" nillable="1">
            <xsd:simpleType>
              <xsd:restriction base="sqltypes:nchar" sqltypes:localeId="1045" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth">
                <xsd:maxLength value="10" />
              </xsd:restriction>
            </xsd:simpleType>
          </xsd:element>
          <xsd:element name="sequence" type="sqltypes:int" nillable="1" />
        </xsd:sequence>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <kategorie xmlns="urn:XMLSCHEMA.pl">
    <id>1</id>
    <higher_id>0</higher_id>
    <Name>Samochod  </Name>
    <sequence>1</sequence>
  </kategorie>
  <kategorie xmlns="urn:XMLSCHEMA.pl">
    <id>2</id>
    <higher_id>0</higher_id>
    <Name>Kemping   </Name>
    <sequence>2</sequence>
  </kategorie>
  <kategorie xmlns="urn:XMLSCHEMA.pl">
    <id>3</id>
    <higher_id>1</higher_id>
    <Name>Fiat      </Name>
    <sequence>1</sequence>
  </kategorie>
  <kategorie xmlns="urn:XMLSCHEMA.pl">
    <id>4</id>
    <higher_id>1</higher_id>
    <Name>Skoda     </Name>
    <sequence>2</sequence>
  </kategorie>
  <kategorie xmlns="urn:XMLSCHEMA.pl">
    <id>7</id>
    <higher_id>3</higher_id>
    <Name>          </Name>
    <sequence>2</sequence>
  </kategorie>
  <kategorie xmlns="urn:XMLSCHEMA.pl">
    <id>5</id>
    <higher_id>1</higher_id>
    <Name>Audi      </Name>
    <sequence>3</sequence>
  </kategorie>
  <kategorie xmlns="urn:XMLSCHEMA.pl">
    <id>6</id>
    <higher_id>2</higher_id>
    <Name>Krotka    </Name>
    <sequence>1</sequence>
  </kategorie>
</ListaKategorie>

Wynik zwróci te same dane jak z przykładu 4, wyłącznie będzie różnić się pseudo-arybutem  xmlns="urn:XMLSCHEMA.pl" Nazwa deklaracja musi spełniać kryteria przestrzeni nazw (ang. Namespace name).

AUTO

Tryb AUTO jest nieco zbliżony do RAW, z tą różnicą, że potrafi budować proste hierarchie w dokumencie XML. Domyślnie generuje nazwę znacznika, taką samą jak nazwa tabeli, a atrybuty są identyczne jak nazwy kolumn. Ponadto obsługuje wszystkie opcje omawiane przy FOR XML RAW. Warto kilka tych informacji przeanalizować na podstawie kilku przykładów:
Przykład 1)
SELECT TOP 3 Os.Nazwisko,Os.IdOsoby,
   Mi.Nazwa
FROM Osoby2 AS Os
   INNER JOIN Miasta AS Mi
   ON Os.IdMiasta = Mi.IdMiasta 
FOR XML AUTO, ROOT('Osoby')

Wyżej wymienione zapytanie SQL, zwraca kolumnę z jednym rekordem jako odnośnik do pliku XML. Gdy użytkownik kliknie na link, otwiera się nowe okno z rekordami zawartymi w instrukcji:
<Osoby>
  <Os Nazwisko="Kot" IdOsoby="46">
    <Mi Nazwa="Dęblin" />
  </Os>
  <Os Nazwisko="Kret" IdOsoby="47">
    <Mi Nazwa="Dęblin" />
  </Os>
  <Os Nazwisko="Zaajac" IdOsoby="81">
    <Mi Nazwa="Dęblin" />
  </Os>
</Osoby>

Pierwszy znacznik jest określony przez klauzurę ROOT('Osoby') . Jeśli nie będzie ona zawarta, wynik będzie reprezentował się bez tego znacznika, a jeśli wyłącznie z ROOT zostanie automatycznie dodany główny znacznik <root> Wewnątrz jego uporządkowanie wyświetlonych znaczników, jest uszeregowane według kolejności podanych nazw tabel w zapytaniu SQL. Nazwy znaczników odpowiadają aliansom nazw tabel podanych w klauzurze FROM . Atrybuty wyświetlone w znaczniku również odpowiadają kolejności wystąpienia w zapytaniu SQL.
Przykład 2)
SELECT TOP 3 Mi.Nazwa, Os.Nazwisko, Os.IdOsoby
FROM Miasta AS Mi
   INNER JOIN Osoby2 AS Os 
   ON  Mi.IdMiasta = Os.IdMiasta 
FOR XML AUTO, ROOT('Osoby'), ELEMENTS XSINIL

Po uruchomieniu odnośnika do dokumentu XML, zostają wyświetlone dane w następujący sposób:
<Osoby xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Mi>
    <Nazwa>Dęblin</Nazwa>
    <Os>
      <Nazwisko>Kot</Nazwisko>
      <IdOsoby>46</IdOsoby>
    </Os>
    <Os>
      <Nazwisko>Kret</Nazwisko>
      <IdOsoby>47</IdOsoby>
    </Os>
    <Os>
      <Nazwisko>Zaajac</Nazwisko>
      <IdOsoby>81</IdOsoby>
    </Os>
  </Mi>
</Osoby>

Zestaw wartości kolumn są teraz uwzględnione jako elementy podrzędne, a nie atrybuty. Dołączenie do elementu znacznika atrybutu xsi:nil="true" dla rekordu o wartości NULL , jest możliwe przez dodanie XSINIL do opcji ELEMENTS .  Dla głównego znacznika został dodany dodatkowo atrybut  xmlns: xsi xmlns:xsi="http:www.w3.org/2001/XMLSchema-instance" //
Przykład 3)
SELECT TOP 3 Mi.Nazwa, Os.Nazwisko, Os.IdOsoby
FROM Miasta AS Mi
   INNER JOIN Osoby2 AS Os 
   ON  Mi.IdMiasta = Os.IdMiasta 
FOR XML AUTO, ROOT('Osoby'),ELEMENTS ,  XMLSCHEMA('urn:XMLSCHEMA.pl'); 

Zapytanie generuje tabele, z zawartością odnośnika. Gdy użytkownik kliknie na niego pojawia się zawartość dokumentu XML w nowym oknie prezentująca się następująco:
<Osoby>
  <xsd:schema targetNamespace="urn:XMLSCHEMA.pl" xmlns:schema="urn:XMLSCHEMA.pl" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
    <xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
    <xsd:element name="Mi">
      <xsd:complexType>
        <xsd:sequence>
          <xsd:element name="Nazwa">
            <xsd:simpleType>
              <xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1045" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth">
                <xsd:maxLength value="50" />
              </xsd:restriction>
            </xsd:simpleType>
          </xsd:element>
          <xsd:element ref="schema:Os" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
      </xsd:complexType>
    </xsd:element>
    <xsd:element name="Os">
      <xsd:complexType>
        <xsd:sequence>
          <xsd:element name="Nazwisko">
            <xsd:simpleType>
              <xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1045" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth">
                <xsd:maxLength value="50" />
              </xsd:restriction>
            </xsd:simpleType>
          </xsd:element>
          <xsd:element name="IdOsoby" type="sqltypes:int" />
        </xsd:sequence>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <Mi xmlns="urn:XMLSCHEMA.pl">
    <Nazwa>Dęblin</Nazwa>
    <Os>
      <Nazwisko>Kot</Nazwisko>
      <IdOsoby>46</IdOsoby>
    </Os>
    <Os>
      <Nazwisko>Kret</Nazwisko>
      <IdOsoby>47</IdOsoby>
    </Os>
    <Os>
      <Nazwisko>Zaajac</Nazwisko>
      <IdOsoby>81</IdOsoby>
    </Os>
  </Mi>
</Osoby>

Wynik ma podobną strukturę jak dokument XML z przykładu 4 dla trybu RAW. Wyświetlenie zawartości danych pozostaje identyczne jak w przykładzie 2 z trybu AUTO. Zmieniony zostaje jedynie atrybut dla każdego pierwszego znacznika w jego obrębie, nie będącym głównym. Dodane zostają również znaczniki informujące o referencji:
<xsd:element ref="schema:Os" minOccurs="0" maxOccurs="unbounded" />
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>
<xsd:element name="Os">
  <xsd:complexType>
    <xsd:sequence>

do tabeli oznaczonej w tym przykładzie aliansem Os . Gdy opcja XMLSCHEMA jest bez parameru zosatje wygenreowany arybut <mi xmlns="urn:schemas-microsoft-com:sql:SqlRowSet9"> , ustalony w analizowanym przykładzie.

EXPLICIT
EXPLICIT ma ściśle określone wymagania co do postaci zbioru wynikowego, który ma być przekształcony na postać dokumentu XML. W klauzuli SELECT pierwsza kolumna musi być nazwana jako Tag . Z kolei druga kolumna posiada nazwę Parent  .Tag oraz Parent są liczbami typu całkowitego.
Przykład 1)
Zapytanie SQL składa się z dwóch zapytań SELECT połączonych operatorem UNION ALL.
SELECT TOP 5
  1 AS Tag,
  NULL AS Parent,   
  u.iducznia AS [uczniowie!1!UczniowieIducznia!ELEMENT],
  NULL AS [uczniowie!2!Nazwisko!ELEMENT],
  NULL AS [uczniowie!2!Imie!ELEMENT]
FROM Klasy k JOIN Uczniowie u
  ON u.idklasy = k.idklasy           
UNION ALL
SELECT TOP 5
  2 AS Tag,
  1 AS Parent,
  k.idklasy,
  k.RokSzkolny,
  k.Nazwa
FROM Klasy k JOIN Uczniowie u
  ON u.idklasy = k.idklasy
FOR XML EXPLICIT; 

Wynik wykonania zapytania, tym razem z klauzulą FOR XML EXPLICIT, zawiera dokument XML o strukturze zaplanowanej przy tworzeniu zapytania.
<uczniowie>
  <UczniowieIducznia>5</UczniowieIducznia>
</uczniowie>
<uczniowie>
  <UczniowieIducznia>6</UczniowieIducznia>
</uczniowie>
<uczniowie>
  <UczniowieIducznia>7</UczniowieIducznia>
</uczniowie>
<uczniowie>
  <UczniowieIducznia>8</UczniowieIducznia>
</uczniowie>
<uczniowie>
  <UczniowieIducznia>9</UczniowieIducznia>
  <uczniowie>
    <Nazwisko>2011/2012</Nazwisko>
    <Imie>Ia</Imie>
  </uczniowie>
  <uczniowie>
    <Nazwisko>2011/2012</Nazwisko>
    <Imie>Ia</Imie>
  </uczniowie>
  <uczniowie>
    <Nazwisko>2011/2012</Nazwisko>
    <Imie>Ia</Imie>
  </uczniowie>
  <uczniowie>
    <Nazwisko>2011/2012</Nazwisko>
    <Imie>IIa</Imie>
  </uczniowie>
  <uczniowie>
    <Nazwisko>2011/2012</Nazwisko>
    <Imie>IIc</Imie>
  </uczniowie>
</uczniowie>

Bez klauzury FOR XML EXPLICIT:
SELECT TOP 5
  1 AS Tag,
  NULL AS Parent,   
  u.iducznia AS [uczniowie!1!UczniowieIducznia!ELEMENT],
  NULL AS [uczniowie!2!Nazwisko!ELEMENT],
  NULL AS [uczniowie!2!Imie!ELEMENT]
FROM Klasy k JOIN Uczniowie u
  ON u.idklasy = k.idklasy           
UNION ALL
SELECT TOP 5
  2 AS Tag,
  1 AS Parent,
  k.idklasy,
  k.RokSzkolny,
  k.Nazwa
FROM Klasy k JOIN Uczniowie u
  ON u.idklasy = k.idklasy; 

Wynik będzie przedstawiła się następująco:
TagParentuczniowie!1!UczniowieIducznia!ELEMENTuczniowie!2!Nazwisko!ELEMENTuczniowie!2!Imie!ELEMENT
1NULL5NULLNULL
1NULL6NULLNULL
1NULL7NULLNULL
1NULL8NULLNULL
1NULL9NULLNULL
2112011/2012Ia
2112011/2012Ia
2112011/2012Ia
2112011/2012IIa
2112011/2012IIc

Wynik kolumn Tag i Parent, przedstawia informacje dotyczące hierarchii. W pierwszym select będą dwie pierwsze kolumny zawsze implementowane w następującej postaci:
[rodzic_wartość],
[NULL],  

Drugi select również będzie miał następującą składnie:
[dziecko_wartość],
[rodzic_wartość],

Nie jest konieczne dodanie aliansu AS . Jednak w naszym przykładzie zostało to zastosowane. W pozostałych kolumnach zostaną wprowadzone wartości NULL .
Każdy rekord otrzymuje swój numer Tag oraz numer Parent. Numery te decydują, gdzie zostaną umieszczone dane z poszczególnych wierszy. Wartość 0 lub NULL dla kolumny Parent wskazują, że odpowiadający element nie posiada rodzica.

PATH
Pomaga w przedstawieniu dokumentu XML. Umieszczenie identyfikatorów jako atrybuty oraz pozostałe wartości przedstwia poniższe zapytanie SQL:
SELECT
 [@kasiaKasia].[dbo].[Osoby2].[IdOsoby] 'IdOsoby',
 [@kasiaKasia].[dbo].[Osoby2].[Nazwisko] [email protected]',
 [@kasiaKasia].[dbo].[Osoby2].[Imie] [email protected]',  
 [@kasiaKasia].[dbo].[Osoby2].[DataUrodzenia] [email protected]',
 [@kasiaKasia].[dbo].[Miasta].[IdMiasta] 'Id_Miasta',
 [@kasiaKasia].[dbo].[Miasta].[Nazwa] [email protected]',
 [@kasiaKasia].[dbo].[Miasta].[IdMiasta] [email protected]'
FROM [@kasiaKasia].[dbo].[Miasta] 
  JOIN [@kasiaKasia].[dbo].[Osoby2] ON [@kasiaKasia].[dbo].[Osoby2].[IdMiasta] = [@kasiaKasia].[dbo].[Miasta].[IdMiasta]
FOR XML PATH('Osoby')

Z powyższego zapytania zostanie wygenerowany link do dokumentu XML, po jego uruchomieniu plik XML , przestawia się w następujący wsposób:
<Osoby>
  <IdOsoby>46</IdOsoby>
  <Osoby Nazwisko="Kot" Imie="Jan" DataUrodzenia="1983-03-12" />
  <Id_Miasta>2</Id_Miasta>
  <Miasta Nazwa="Dęblin" IdMiasta="2" />
</Osoby>
<Osoby>
  <IdOsoby>47</IdOsoby>
  <Osoby Nazwisko="Kret" Imie="Zosia" DataUrodzenia="1983-03-15" />
  <Id_Miasta>2</Id_Miasta>
  <Miasta Nazwa="Dęblin" IdMiasta="2" />
</Osoby>
<Osoby>
  <IdOsoby>81</IdOsoby>
  <Osoby Nazwisko="Zaajac" Imie="Helena" DataUrodzenia="1977-09-09" />
  <Id_Miasta>2</Id_Miasta>
  <Miasta Nazwa="Dęblin" IdMiasta="2" />
</Osoby>

Dokument XML przedstawiła elementy <osoby> Dla każdego z nich są wyświetlony rekord osoby. Zastosowanie @ prowadzi do wypisania atrybutów, zgodnie z nazwą kolumn. Umieszczenie nowego węzła można uzyskać poprzez wprowadzenie '/'. Nazwa atrybutu podaję się w cudy słowniach, nie jest konieczne wprowadzanie identycznych jak nazwy kolumn.

Typ danych XML zawiera pięć metod, które mają za zadanie manipulować zawartością dokumentu XML oraz modyfikować dokument. Dodatkowo dają one możliwość wykonania operacji odwrotnej do działania klauzuli FOR XML – czyli do przetransformowania danych z XML w wiersz zbioru wyników (rowset).
Wyrażenia metod zbudowane są oparte o podstawy języka XQuery oraz XPath:
Value - zwraca wskazana wartość skalarną (zawartość atrybutu lub elementu)
Query - zwraca wskazany XML
Exists - zwraca wartość logiczną określająca czy wskazany element istnieje w dokumencie XML
Nodes - zwraca wskazane węzły dokumenty XML
Modify - umożliwia operacje modyfikacji dokumentu XML