Spis treści:

Kategoria:HTMLSQL ServerXQuery


Tworzenie tabeli HTML przy pomocy SQL Server - XQuery

Jakiś czas temu pokazywałem, w jaki sposób stworzyć tabelę HTML przy pomocy instrukcji SELECT w SQL Server. Wtedy kluczem do rozwiązania okazała się instrukcja FOR XML. Pisałem też, że istnieją inne metody. Obiecałem też, że wkrótce przedstawię inne, alternatywne rozwiązanie. Żeby nie pozostać gołosłownym, zademonstruję metodę z wykorzystaniem XQuery.

Czym jest XQuery

XQuery to, nie bójmy się użyć tego słowa, język programowania, który służy do wykonywania operacji na zbiorach danych w postaci XML. W głowach powinna już się zapalić lampka i oświetlić związki HTML - XML - XHTML. Jest to powszechny standard wspierany oficjalnie przez W3C. Na tyle powszechny, że twórcy silnika bazy danych SQL Server zadbali o pełną integrację XQuery z całą resztą. Trzeba wiedzieć, że możliwość przetwarzania dokumentów XML pojawiła się w wersji SQL Server 2005 - razem z typem XML, instrukcją FOR XML i innymi elementami związanymi z danymi XML. Celem artykułu nie jest nauka języka XQuery. Ze względu na złożoność wypadałoby poświęcić mu całą książkę, a nie skromny wpis. Celem artykułu jest pokazanie, jakie są możliwości języka XQuery wbudowanego w SQL Server, na tytułowym przykładzie, czyli na etapie tworzenia tabeli HTML.

Zapytanie na typie XML

Trzeba sobie powiedzieć i zrozumieć, że instrukcje XQuery możemy wykonywać tylko na dokumencie XML (zmiennej typu xml). Samą instrukcję, składającą się ze słowa kluczowego query, umieszcza się przy zmiennej, poprzedzając kropką. Następnie, w nawiasie okrągłym, podaje się instrukcje języka XQuery w postaci tekstowej. Nie jest to tak strasznie skomplikowane jak by się mogło wydawać. Przyjrzyjmy się przykładowi i przeanalizujmy go:

--Tworzymy przykładową tabelę
CREATE TABLE Programy
(
ID int identity(1,1),
Nazwa varchar(16),
Rok int
)

--Wstawiamy jakieś wartości
INSERT INTO Programy VALUES
('SQL Server', 2005),
('SQL Server', 2008),
('Visual Studio', 2003),
('Visual Studio', 2005),
('Visual Studio', 2008),
('Visual Studio', 2010)

--Tworzymy tabelę HTML
DECLARE @xml xml
SET @xml = (SELECT *
FROM Programy
FOR XML AUTO)

SELECT @xml.query('
<table>
<tr>
  <th>ID</th>
  <th>Nazwa programu</th>
  <th>Rok wydania</th>
</tr>
{
for $i in /Programy order by $i/@Rok
return
  <tr>
    <td>{data($i/@ID)}</td>
    <td>{data($i/@Nazwa)}</td>
    <td>{data($i/@Rok)}</td>
  </tr>
}
</table>'
)

Przeanalizujmy powyższy listing. Jak zwykle, aby nie działać w próżni, tworzymy sobie tabelę, uzupełniamy ją danymi. Następnie deklarujemy zmienną @xml typu xml i przypisujemy jej wynik instrukcji SELECT ... FOR XML. Pisałem na początku, że XQuery to język przetwarzania dokumentów XML. Nie da się stosować XQuery na zwykłej instrukcji SELECT, bo wynikiem takiej zwykłej operacji nie jest dokument XML. Nasze wyniki lądują zatem w zmiennej typu xml, co pozwala nam na skorzystanie z XQuery. Piszemy zatem SELECT, nazwę zmiennej, kropkę, instrukcję query, a w nawiasie, w postaci tekstowej, podajemy instrukcje XQuery. Na tym kończy się SQL Server jako taki, a zaczyna XQuery.

Wyjaśnienie instrukcji XQuery

Wszystko, co znajduje się poza nawiasem klamrowym traktowane jest jako pewnego rodzaju stały tekst. Ten stały tekst będzie bezpośrednio zwrócony w postaci wyniku. Są to instrukcje definiujące znaczniki table oraz nagłówek tejże tabeli, czyli znaczniki th. Całą procedurę przetwarzania dokumentu wejściowego umieszcza się wewnątrz nawiasów klamrowych. Taki blok będę nazywał blokiem instrukcji. To właśnie tam znajduje się instrukcja for. Zanim przejdziemy dalej, przyjrzyjmy się zawartości zmiennej @xml:

<Programy ID="1Nazwa="SQL ServerRok="2005/>
<Programy ID="2Nazwa="SQL ServerRok="2008/>
<Programy ID="3Nazwa="Visual StudioRok="2003/>
<Programy ID="4Nazwa="Visual StudioRok="2005/>
<Programy ID="5Nazwa="Visual StudioRok="2008/>
<Programy ID="6Nazwa="Visual StudioRok="2010/>

Potrzebne jest tutaj drobne wyjaśnienie. Nie jest to dokument XML, bo nie posiada elementu głównego. Nie stanowi to jednak przeszkody, dlatego nie ma potrzeby wykonywania żadnych dodatkowych operacji. Wróćmy zatem do instrukcji for. Elementy dokumentu XML wskazujemy za pomocą samej nazwy poprzedzonej ukośnikiem, a atrybuty za pomocą nazwy umieszczonej za symbolem @ (całość również poprzedzona ukośnikiem, jeżeli jest to element podrzędny).

Sam język XQuery jest dużo bardziej skomplikowany. Przedstawione wyjaśnienia są bardzo powierzchowne i mają na celu tylko wyjaśnienie zaprezentowanego przykładu. Postaram się poruszyć ciekawsze techniki w innym wpisie.

Z przedstawionego pseudodokumentu XML pobierane są wszystkie elementy Programy za pomocą klucza /Programy, a każdy taki element trafia do zmiennej lokalnej $i (zmienne poprzedzamy znakiem $). Zanim tam jednak trafi, wykonywana jest operacja sortowania. Służy do tego instrukcja order by, pisana dokładnie tak samo jak w języku SQL. Warto zwrócić uwagę na względne pobranie atrybutu z elementu /Programy.

Element /Programy staje się w tym momencie zmienną $i. My wybieramy atrybut Rok znajdujący się wewnątrz elementu (piszemy $i/@Rok) i po nim sortujemy. Dla każdego z rekordów zwróconych przez instrukcję for zwracamy jeden rząd tabeli, czyli atrybut tr, atrybuty td i oczywiście dane. Dane zwracane są za pomocą funkcji data, która również przyjmuje instrukcję XQuery. Są to atrybuty pobierane względnie ze zmiennej $i, której zasięg obowiązuje wewnątrz rozpatrywanej pętli for. Aby wypisać wartość, a nie tekst, należy umieścić funkcję data wewnątrz bloku instrukcji, czyli wewnątrz nawiasów klamrowych { }. Wynikiem działania powyższej instrukcji będzie taki oto rezultat:

<table>
  <tr>
    <th>ID</th>
    <th>Nazwa programu</th>
    <th>Rok wydania</th>
  </tr>
  <tr>
    <td>3</td>
    <td>Visual Studio</td>
    <td>2003</td>
  </tr>
  <tr>
    <td>1</td>
    <td>SQL Server</td>
    <td>2005</td>
  </tr>
  <tr>
    <td>4</td>
    <td>Visual Studio</td>
    <td>2005</td>
  </tr>
  <tr>
    <td>2</td>
    <td>SQL Server</td>
    <td>2008</td>
  </tr>
  <tr>
    <td>5</td>
    <td>Visual Studio</td>
    <td>2008</td>
  </tr>
  <tr>
    <td>6</td>
    <td>Visual Studio</td>
    <td>2010</td>
  </tr>
</table>

Postać HTML przedstawia się mniej więcej tak (po uwzględnieniu zewnętrznego stylu):

ID Nazwa programu Rok wydania
3 Visual Studio 2003
1 SQL Server 2005
4 Visual Studio 2005
2 SQL Server 2008
5 Visual Studio 2008
6 Visual Studio 2010

Wynik końcowy jest zadowalający. Gdybym miał zdecydować, która z przedstawionych metod generowania tabeli HTML jest dla mnie wygodniejsza, wybrałbym XQuery. Przede wszystkim dlatego, że jest bardziej czytelna. Drugą zaletą jest większa elastyczność tej metody. Gdybyśmy chcieli dodać elementy html, head, body i wygenerować cały plik HTML, wtedy ujrzelibyśmy moc i przejrzystość XQuery. W przypadku FOR XML napotkalibyśmy na większe problemy. Oddzielny wątek wypadałoby poświęcić wydajności obu rozwiązań. O tym jednak innym razem...

Kategoria:HTMLSQL ServerXQuery

, 2013-12-20

Komentarze:

Pierwszy (2014-11-09 13:15:32)
Bardzo fajnie napisany artykuł. Pozdrowienia dla Autora
Dodaj komentarz
Wyślij
Ostatnie komentarze
Dzieki za rozjasnienie zagadnienia upsert. wlasnie sie ucze programowania :).
Co się stanie gdy spróbuję wyszukać:
SELECT * FROM NV_Airport WHERE Code='SVO'
SELECT * FROM V_Airport WHERE Code=N'SVO'
(odwrotnie są te N-ki)
Będzie konwersja czy nie znajdzie żadnego rekordu?