Microsoft SQL Server 2000
umożliwiał export relacyjnych danych z i do XML. Jednakże jedynym
sposobem na przechowywanie danych typu XML było pole typu string. Jest to
bardzo nieefektywny sposób przechowywania tego typu danych. Ograniczenia jakie
to powoduje można mnożyć:
- brak
możliwości sprawdzenia poprawności XML
- brak
możliwości wyszukiwania odpowiednich tagów
- brak możliwości zmiany poszczególnych wartości
Oczywiście wszystkie te problemy można ominąć poprzez napisanie
odpowiednich funkcji bazodanowych. Ale żadna z tych opcji nie jest udostępniona
przez starszą wersje serwera.
Większość tych ograniczeń została
usunięta w SQL Server 2005 dzięki wprowadzanie typu danych XML.
Pole to może być indeksowane, zmieniane i oczywiście bez żadnych problemów
przeglądane. Dodatkowo został udostępniony nowy język XQuery, za
pomocą którego możemy bezpośrednio manipulować na danych, zmieniać dane zaszyte
wewnątrz któregoś z pól XML oraz wyciągać pojedyncze wartości.
Jak wcześniej wspomniałem głównym zastosowaniem
XML jest
komunikacja. Zacznijmy więc od bardzo życiowego przypadku. Jesteśmy
administratorem bazy danych w firmie AdventureWorks i dostaliśmy
bezpośrednie polecenia na utworzenie bilansu sprzedaży każdego z produktów.
Ponieważ nasz przełożony używa Excela musimy mu podać dane w takim formacie,
aby program ten bez problemu mógł sobie z nimi poradzić. Oczywiście rozwiązaniem
naszego problemu będzie XML. Najpierw musimy stworzyć odpowiednie
zapytanie, ale to już nie powinno nam sprawić problemów.
SELECT [Production].[Product].[Name],
SUM(OrderQty) AS Quantity
FROM [Sales].[SalesOrderHeader]
INNER JOIN [Sales].[SalesOrderDetail]
ON [Sales].[SalesOrderHeader].[SalesOrderID]
= [Sales].[SalesOrderDetail].[SalesOrderID]
INNER JOIN
[Production].[Product]
ON
[Production].[Product].[ProductID] = [Sales].[SalesOrderDetail].[ProductID]
GROUP BY
[Production].[Product].ProductID, [Production].[Product].[Name]
ORDER BY Quantity DESC
Teraz wystarczy dodać do
naszego zapytania klauzulę FOR XML AUTO i już mamy gotowy plik,
który możemy bezpośrednio wysłać do osoby zamawiającej.
SELECT [Production].[Product].[Name],
SUM(OrderQty) AS Quantity
FROM [Sales].[SalesOrderHeader]
INNER JOIN [Sales].[SalesOrderDetail]
ON
[Sales].[SalesOrderHeader].[SalesOrderID] =
[Sales].[SalesOrderDetail].[SalesOrderID]
INNER JOIN
[Production].[Product]
ON
[Production].[Product].[ProductID] = [Sales].[SalesOrderDetail].[ProductID]
GROUP BY [Production].[Product].ProductID,
[Production].[Product].[Name]
ORDER BY Quantity DESC
FOR XML AUTO
Jak widać, nie ma potrzeby
rozpisywać się, jak działa powyższa składnia. Poprzez proste dodanie do
zapytanie klauzuli otrzymujemy wynik w postaci XML. Gdy dodamy do
naszej opcji FOR XML AUTO dodatkową instrukcję ELEMENTS, będziemy mogli
zmienić sposób organizacji danych. Nie mamy już jednego elementu i dane jako
atrybuty, lecz dane które wcześniej były atrybutami teraz są jak elementy w
nagłówku Produkt.
SELECT [Production].[Product].[Name],
SUM(OrderQty) AS Quantity
FROM [Sales].[SalesOrderHeader]
INNER JOIN
[Sales].[SalesOrderDetail]
ON
[Sales].[SalesOrderHeader].[SalesOrderID] =
[Sales].[SalesOrderDetail].[SalesOrderID]
INNER JOIN
[Production].[Product]
ON
[Production].[Product].[ProductID] = [Sales].[SalesOrderDetail].[ProductID]
GROUP BY [Production].[Product].ProductID,
[Production].[Product].[Name]
ORDER BY Quantity DESCFOR XML AUTO, ELEMENTS
Dzięki użyciu nowej opcji TYPE
w klauzuli FOR XML mamy możliwość traktowania wyników jako
pojedynczej kolumny w głównym zapytaniu z informacją o nagłówku.
Kolejną nową opcją, do jakiej
mamy dostęp w opcji FOR XML jest PATH. Ułątwia ona
bardziej świadome tworzenie konstrukcji XML z możliwością tworzenia
pojedynczych pól typu XML wewnątrz tabel. Poniższy przykład
pokazuje, jak możemy stworzyć z danych już istniejących tabelę z polem XML.
SELECT TOP 2
SalesOrderHeader.SalesOrderID AS SalesOrderID,
OrderDate AS OrderDate,
CustomerID AS CustomerID,
(SELECT ProductID AS '@ProductID',
OrderQty AS
'@OrderQty',
UnitPrice AS '@UnitPrice'
FROM
Sales.SalesOrderDetail AS SalesOrderDetail
WHERE
SalesOrderDetail.SalesOrderID = SalesOrderHeader.SalesOrderID
FOR XML PATH
('SalesOrderDetail'), type) AS 'ProductsLine'
FROM Sales.SalesOrderHeader AS
SalesOrderHeader
FOR XML
PATH ('SalesOrderHeader')
Skrypt ten wymaga małego wyjaśnienia. Po pierwsze: nazwa
kolumny określa ścieżkę w XML. Argument za opcją Path
określa nazwę kolumny. Prefiks @ mówi, że kolumna wynikowa jest atrybutem, a
nie elementem w polu XML.