XML w relacyjnych bazach danych

kasiaKasia

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]
IdOsoby Nazwisko Imie DataUrodzenia CzyKobieta Pesel IdMiasta Znacznik plec wiek nic
45 Kot Janina 1985-07-29 1 85072911986 1 0x00000000000007FD Kobieta 27 NULL
46 Kot Jan 1983-03-12 1 83031234501 2 0x00000000000007FE Kobieta 29 NULL
47 Kret Zosia 1983-03-15 1 83031534581 2 0x00000000000007FF Kobieta 29 NULL
74 Piasek Zosia 1987-04-29 1 87042945367 8 0x000000000000081E Kobieta 25 NULL
75 Piasek Zosia 1987-04-29 1 87042945367 8 0x000000000000081F Kobieta 25 NULL
76 Piasek Zosia 1987-04-29 1 87042945367 8 0x0000000000000820 Kobieta 25 NULL
77 Piasek Zosia 1987-04-29 1 87042945367 8 0x0000000000000821 Kobieta 25 NULL
79 Zajac Helena 1977-09-09 1 77090934567 1 0x0000000000000823 Kobieta 35 NULL
81 Zaajac Helena 1977-09-09 1 77090934567 2 0x0000000000000825 Kobieta 35 NULL
82 Krolik Jan 1988-08-08 0 88080834556 9 0x0000000000000826 Mężczyzna 24 NULL
83 Krolik Jan 1988-08-08 0 88080834556 9 0x0000000000000827 Mężczyzna 24 NULL
84 Jenot Janina 1988-08-08 1 88080834546 10 0x0000000000000828 Kobieta 24 NULL

[Tabela: Miasta]

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

[Tabela: kategorie]

id higher_id Name Sequence
1 0 Samochod 1
2 0 Kemping 2
3 1 Fiat 1
4 1 Skoda 2
7 3 2
5 1 Audi 3
6 2 Krotka 1

[Tabela: Klasy]

idklasy Nazwa RokSzkolny cos
1 Ia 2011/2012 sshhhdgguu
2 IIa 2011/2012 sshhhdgguu
3 IIc 2011/2012 sshhhdgguu
4 IVb 2011/2012 sshhhdgguu
5 IId 2011/2012 sshhhdgguu
6 Va 2011/2012 sshhhdgguu
13 Ic 2011/2012 sshhhdgguu
14 VIa 2011/2012 sshhhdgguu
15 VIa 2011/2012 sshhhdgguu
16 Vb 2011/2012 sshhhdgguu
18 Vc 2011/2012 sshhhdgguu
20 Vd 2012/2012 sshhhdgguu
21 Ve 2012/2012 sshhhdgguu
22 Vf 2012/2012 sshhhdgguu
23 Vg 2012/2012 sshhhdgguu
24 IIe 2012/2012 sshhhdgguu

[Tabela: Uczniowie]

iducznia Nazwisko Imie DataUrodzenia CzyChlopak Pesel idklasy
1 InnyGość NULL 1410-07-14 0 10071451147 2
3 Gazela Basia 1992-02-22 0 92022277654 2
4 Kurka Jola 1992-06-02 0 92060288788 2
5 Gąska Wacek 1991-03-11 1 91031199123 1
6 Krówka Rysio 1992-05-15 1 92051577646 1
7 Zebra Wojtek 1993-03-13 1 93030399846 1
8 Gazela Basia 1992-11-11 0 92111177446 2
9 Sarenka Rysio 1992-12-12 0 92121278766 3
10 Konik Kasia 1993-03-12 0 93031275446 2
11 Ryba Jan 1993-05-15 1 93051587746 2
12 Kura Kasia 1993-02-22 0 93022277654 2
13 Łoś Jola 1993-06-02 0 93060288788 2
14 Miś Wacek 1993-03-11 1 93031199123 4
15 Okoń Rysio 1993-05-15 1 93051577646 4
16 Płotka Wojtek 1993-03-13 1 93030399846 2
17 Różyczka Basia 1993-11-11 0 93111177446 2
18 Stokrotka Rysio 1993-12-12 0 93121278766 2
19 Wilczek Jasio 1999-12-12 0 99121209876 3
  • 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-comSqlRowSet9"> * , 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:

Tag Parent uczniowie!1!UczniowieIducznia!ELEMENT uczniowie!2!Nazwisko!ELEMENT uczniowie!2!Imie!ELEMENT
1 NULL 5 NULL NULL
1 NULL 6 NULL NULL
1 NULL 7 NULL NULL
1 NULL 8 NULL NULL
1 NULL 9 NULL NULL
2 1 1 2011/2012 Ia
2 1 1 2011/2012 Ia
2 1 1 2011/2012 Ia
2 1 1 2011/2012 IIa
2 1 1 2011/2012 IIc
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] 'Osoby/@Nazwisko',
 [@kasiaKasia].[dbo].[Osoby2].[Imie] 'Osoby/@Imie',  
 [@kasiaKasia].[dbo].[Osoby2].[DataUrodzenia] 'Osoby/@DataUrodzenia',
 [@kasiaKasia].[dbo].[Miasta].[IdMiasta] 'Id_Miasta',
 [@kasiaKasia].[dbo].[Miasta].[Nazwa] 'Miasta/@Nazwa',
 [@kasiaKasia].[dbo].[Miasta].[IdMiasta] 'Miasta/@IdMiasta'
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

0 komentarzy