0
Tải bản đầy đủ (.pdf) (69 trang)

Cách sinh ram ột tài liệu XML trong SQL Server 29

Một phần của tài liệu NGHIÊN CỨU MỘT SỐ KỸ THUẬT KHAI PHÁ DỮ LIỆU XML ỨNG DỤNG TRONG THỰC HIỆN XỬ LÝ DỮ LIỆU QUAN HỆ (Trang 30 -43 )

Trong SQL Server, để tạo ra một tài liệu XML ta sử dụng cú pháp sau:

Để tìm hiểu kỹ hơn, ta từng bước đi vào từng cú pháp trong cú pháp lệnh SQL trên. Ta thực hành trên CSDL Northwind với các bảng dữ liệu Customer, Products, Order details.

Trước tiên, ta tìm hiểu cú pháp lệnh: FOR XML {RAW[('ElementName')]} FOR XML {{RAW[('ElementName')]|AUTO}|EXPLICIT|PATH[('ElementName')]} [,BINARY BASE64] [,TYPE] [,ROOT[('RootName')]

- 30 -

Cú pháp này cho kết quả là một tài liệu XML phân mảnh (không có phần tử gốc) và các phần tử XML này sử dụng chung một định danh nằm trong thẻ <row /> trong trường hợp sử dụng định danh khác cho thẻ thì ta sẽ truyền định danh này vào với dạng ‘ElementName’. Ví dụ:

Hoặc sử dụng định danh:

Trong trường hợp dữ liệu được truy vấn từ nhiều bảng dữ liệu: Ví dụ 1:

SELECT CustomerID, ContactName, Country FROM Customers

WHERE Country = 'Spain' FOR XML RAW

Kết quả như sau:

<row CustomerID="BOLID" ContactName="Martín Sommer" Country="Spain" /> <row CustomerID="FISSA" ContactName="Diego Roel" Country="Spain" /> <row CustomerID="GALED" ContactName="Eduardo Saavedra" Country="Spain" />

<row CustomerID="GODOS" ContactName="José Pedro Freyre" Country="Spain" />

<row CustomerID="ROMEY" ContactName="Alejandra Camino" Country="Spain" />

Ví dụ 2:

SELECT CustomerID, ContactName, Country FROM Customers

WHERE Country = 'Spain' FOR XML RAW('CustomerInfo')

Kết quả như sau:

<CustomerInfo CustomerID="BOLID" ContactName="Martín Sommer" Country="Spain" />

<CustomerInfo CustomerID="FISSA" ContactName="Diego Roel" Country="Spain" />

<CustomerInfo CustomerID="GALED" ContactName="Eduardo Saavedra" Country="Spain" />

<CustomerInfo CustomerID="GODOS" ContactName="José Pedro Freyre" Country="Spain" />

<CustomerInfo CustomerID="ROMEY" ContactName="Alejandra Camino" Country="Spain" />

- 31 -

Tiếp theo, ta tìm hiểu cú pháp:

FOR XML {AUTO}

Cú pháp này cho kết quả là một tài liệu XML phân mảnh và các phần tử XML này sử dụng chung một định danh nằm trong thẻ <Customers /> - là tên của bảng được truy vấn. Ví dụ:

Trong trường hợp dữ liệu được truy vấn từ nhiều bảng kết quả trả về là tài liệu xml phân mảnh trong đó mỗi phần tử XML có tên là bảng đầu tiên được truy vấn đến, có thuộc tính là các trường dữ liệu tồn tại trong bảng đó và các phần tử con là các bảng tiếp theo được truy vấn, các phần tử con này cũng chứa thuộc tính là các trường dữ liệu trong bảng tiếp theo, ví dụ:

Ví dụ 3:

SELECT P.ProductID, ProductName, UnitPrice=ROUND(P.UnitPrice, 2),

Quantity,

Discount=CONVERT(int, Discount * 100),

ExtendedPrice=ROUND(CONVERT(money, Quantity *(1 - Discount) *

P.UnitPrice), 2)

FROM Products P, [Order Details] Od

WHERE Od.ProductID = P.ProductID and Od.OrderID = 10248 FOR XML RAW

Kết quả như sau:

<row ProductID="11" ProductName="Queso Cabrales" UnitPrice="21.0000" Quantity="12" Discount="0" ExtendedPrice="252.0000" />

<row ProductID="42" ProductName="Singaporean Hokkien Fried Mee" UnitPrice="14.0000" Quantity="10" Discount="0"

ExtendedPrice="140.0000" />

<row ProductID="72" ProductName="Mozzarella di Giovanni"

UnitPrice="34.8000" Quantity="5" Discount="0" ExtendedPrice="174.0000" />

Ví dụ 4:

SELECT CustomerID, ContactName, Country FROM Customers

WHERE Country = 'Spain' FOR XML AUTO

Kết quả như sau:

<Customers CustomerID="BOLID" ContactName="Martín Sommer" Country="Spain" />

<Customers CustomerID="FISSA" ContactName="Diego Roel" Country="Spain" />

<Customers CustomerID="GALED" ContactName="Eduardo Saavedra" Country="Spain" />

<Customers CustomerID="GODOS" ContactName="José Pedro Freyre" Country="Spain" />

<Customers CustomerID="ROMEY" ContactName="Alejandra Camino" Country="Spain" />

- 32 -

Tiếp theo, ta tìm hiểu cú pháp:

FOR XML EXPLICIT

Cú pháp này ít được dùng hơn do yêu cầu chặt chẽ về mặt cú pháp sử dụng, song đây là cú pháp có thể tạo ra được nhiều kiểu cấu trúc XML khác nhau tùy theo yêu cầu của người sử dụng. Đối với cú pháp này cần có các điều kiện sau:

- Cột đầu tiên phải ở dạng số nguyên và duy nhất đối với từng dòng dữ liệu ( thường là kiểu ID), tên của cột sẽ trở thành thẻ.

- Cột thứ hai cung cấp một số thẻ của phần tử cha, và tên cột này sẽ trở thành cha, bằng cách này các thẻ sẽ cung cấp các thông tin cho ta.

- Các cột còn lại sẽ mang các giá trị cùng với các thông tin trong tên cột và dùng để tạo ra các dữ liệu XML, và ta cũng có thể định dạng lại các dữ liệu này để có được các tài liệu XML khác nhau thông qua các chỉ thị.

Chẳng hạn, đểđưa ra được kết quả như trong ví dụ 5 ta phải làm như sau: Ví dụ 5:

SELECT P.ProductID, ProductName, UnitPrice=ROUND(P.UnitPrice, 2),

Quantity,

Discount=CONVERT(int, Discount * 100),

ExtendedPrice=ROUND(CONVERT(money, Quantity *(1 - Discount) *

P.UnitPrice), 2)

FROM Products P, [Order Details] Od

WHERE Od.ProductID = P.ProductID and Od.OrderID = 10248 FOR XML AUTO

Kết quả như sau:

<P ProductID="11" ProductName="Queso Cabrales" UnitPrice="21.0000"> <Od Quantity="12" Discount="0" ExtendedPrice="252.0000" />

</P>

<P ProductID="42" ProductName="Singaporean Hokkien Fried Mee" UnitPrice="14.0000">

<Od Quantity="10" Discount="0" ExtendedPrice="140.0000" /> </P>

<P ProductID="72" ProductName="Mozzarella di Giovanni" UnitPrice="34.8000">

<Od Quantity="5" Discount="0" ExtendedPrice="174.0000" /> </P>

- 33 -

Ngoài ra ta có thể hiển thị tài liệu XML theo cách khác thông qua việc sử dụng thêm một số các chỉ thị dịch khác, chẳng hạn chỉ thị Element biến giá trị của phần tử thành giá trị của thuộc tính:

Ví dụ 6:

SELECT 1 AS Tag, NULL AS Parent, P.ProductID AS [P!1!ProductID], P.ProductName AS [P!1!ProductName], P.UnitPrice AS [P!1!UnitPrice],

NULL AS [Od!2!Quantity], Null as [Od!2!Discount], null as [Od!2!ExtendedPrice]

FROM Products P, [Order Details] Od

WHERE Od.ProductID = P.ProductID and Od.OrderID = 10248 UNION ALL

SELECT 2 AS Tag, 1 AS Parent, P.ProductID, P.ProductName, P.UnitPrice,

Quantity, Discount=CONVERT(int, Discount * 100),

ExtendedPrice=ROUND(CONVERT(money, Quantity *(1 - Discount) *

P.UnitPrice), 2)

FROM Products P, [Order Details] Od

WHERE Od.ProductID = P.ProductID and Od.OrderID = 10248 ORDER BY [P!1!ProductID], [Od!2!Quantity]

FOR XML EXPLICIT

Kết quả như sau:

<P ProductID="11" ProductName="Queso Cabrales" UnitPrice="21.0000"> <Od Quantity="12" Discount="0" ExtendedPrice="252.0000" />

</P>

<P ProductID="42" ProductName="Singaporean Hokkien Fried Mee" UnitPrice="14.0000">

<Od Quantity="10" Discount="0" ExtendedPrice="140.0000" /> </P>

<P ProductID="72" ProductName="Mozzarella di Giovanni" UnitPrice="34.8000">

<Od Quantity="5" Discount="0" ExtendedPrice="174.0000" /> </P>

- 34 -

Ví dụ 7:

SELECT 1 AS Tag, NULL AS Parent, P.ProductID AS [P!1!ProductID], P.ProductName AS [P!1!ProductName], P.UnitPrice AS [P!1!UnitPrice],

NULL AS [Od!2!Quantity!Element], Null as

[Od!2!Discount!Element], null as [Od!2!ExtendedPrice!Element] FROM Products P, [Order Details] Od

WHERE Od.ProductID = P.ProductID and Od.OrderID = 10248 UNION ALL

SELECT 2 AS Tag, 1 AS Parent, P.ProductID, P.ProductName, P.UnitPrice,

Quantity, Discount=CONVERT(int, Discount * 100),

ExtendedPrice=ROUND(CONVERT(money, Quantity *(1 - Discount) *

P.UnitPrice), 2)

FROM Products P, [Order Details] Od

WHERE Od.ProductID = P.ProductID and Od.OrderID = 10248 ORDER BY [P!1!ProductID], [Od!2!Quantity!Element] FOR XML EXPLICIT

Kết quả như sau:

<P ProductID="11" ProductName="Queso Cabrales" UnitPrice="21.0000"> <Od> <Quantity>12</Quantity> <Discount>0</Discount> <ExtendedPrice>252.0000</ExtendedPrice> </Od> </P>

<P ProductID="42" ProductName="Singaporean Hokkien Fried Mee" UnitPrice="14.0000"> <Od> <Quantity>10</Quantity> <Discount>0</Discount> <ExtendedPrice>140.0000</ExtendedPrice> </Od> </P>

<P ProductID="72" ProductName="Mozzarella di Giovanni" UnitPrice="34.8000"> <Od> <Quantity>5</Quantity> <Discount>0</Discount> <ExtendedPrice>174.0000</ExtendedPrice> </Od> </P>

Hoặc sử dụng chỉ thị CDATA, chỉ thị này thường được sử dụng khi giá trị của phần tử có các ký tự vi phạm luật của một tài liệu XML, khi đó sử dụng chỉ thị này các công cụ sử dụng đọc tài liệu XML sẽ tự động bỏ qua các giá trị trong thẻ này:

- 35 -

Tiếp theo, ta tìm hiểu cú pháp:

FOR XML {PATH[('ElementName')]}

Khác với cú pháp FOR XML EXPLICIT, cú pháp FOR XML {PATH [(‘ElementName’)]} có thể tạo ra được nhiều kiểu cấu trúc xml khác nhau từ đơn giản đến phức tạp theo yêu cầu của người sử dụng bằng cách sử dụng bộ các quy tắc cho sẵn. Ở mức độ đơn giản, ta dễ dàng tạo được các tài liệu XML, ngoài ra có thể dùng các chỉ thị dịch khác nhau để tạo nên các tài liệu XML khác ở mức độ phức tạp hơn.

Ví dụ 8:

SELECT 1 AS Tag, NULL AS Parent, P.ProductID AS [P!1!ProductID], P.ProductName AS [P!1!ProductName!CDATA], P.UnitPrice AS

[P!1!UnitPrice],

NULL AS [Od!2!Quantity!Element], Null as [Od!2!Discount], null as [Od!2!ExtendedPrice]

FROM Products P, [Order Details] Od

WHERE Od.ProductID = P.ProductID and Od.OrderID = 10248 UNION ALL

SELECT 2 AS Tag, 1 AS Parent, P.ProductID, P.ProductName, P.UnitPrice,

Quantity, Discount=CONVERT(int, Discount * 100),

ExtendedPrice=ROUND(CONVERT(money, Quantity *(1 - Discount) *

P.UnitPrice), 2)

FROM Products P, [Order Details] Od

WHERE Od.ProductID = P.ProductID and Od.OrderID = 10248 ORDER BY [P!1!ProductID], [Od!2!Quantity!Element] FOR XML EXPLICIT

Kết quả như sau:

<P ProductID="11" UnitPrice="21.0000">

<ProductName><![CDATA[Queso Cabrales]]></ProductName> <Od Discount="0" ExtendedPrice="252.0000">

<Quantity>12</Quantity> </Od>

</P>

<P ProductID="42" UnitPrice="14.0000">

<ProductName><![CDATA[Singaporean Hokkien Fried Mee]]></ProductName> <Od Discount="0" ExtendedPrice="140.0000">

<Quantity>10</Quantity> </Od>

</P>

<P ProductID="72" UnitPrice="34.8000">

<ProductName><![CDATA[Mozzarella di Giovanni]]></ProductName> <Od Discount="0" ExtendedPrice="174.0000">

<Quantity>5</Quantity> </Od>

- 36 -

Khi ta thay đổi cú pháp thì cũng sẽ nhận được các giá trị khác nhau, chẳng hạn khi đặt tên cho cột bắt đầu bởi ký tự “@” và trong tên của cột không chứa ký tự “/” thì cột thay vì hiển thị là giá trị sẽ chuyển thành thuộc tính của phần tử trong tài liệu xml, như sau:

Ví dụ 9:

SELECT P.ProductID, ProductName, UnitPrice=ROUND(P.UnitPrice, 2),

Quantity,

Discount=CONVERT(int, Discount * 100),

ExtendedPrice=ROUND(CONVERT(money, Quantity *(1 - Discount) *

P.UnitPrice), 2)

FROM Products P, [Order Details] Od

WHERE Od.ProductID = P.ProductID and Od.OrderID = 10248 FOR XML PATH

Kết quả như sau:

<row>

<ProductID>11</ProductID>

<ProductName>Queso Cabrales</ProductName> <UnitPrice>21.0000</UnitPrice> <Quantity>12</Quantity> <Discount>0</Discount> <ExtendedPrice>252.0000</ExtendedPrice> </row> <row> <ProductID>42</ProductID>

<ProductName>Singaporean Hokkien Fried Mee</ProductName> <UnitPrice>14.0000</UnitPrice> <Quantity>10</Quantity> <Discount>0</Discount> <ExtendedPrice>140.0000</ExtendedPrice> </row> <row> <ProductID>72</ProductID>

<ProductName>Mozzarella di Giovanni</ProductName> <UnitPrice>34.8000</UnitPrice>

<Quantity>5</Quantity> <Discount>0</Discount>

<ExtendedPrice>174.0000</ExtendedPrice> </row>

- 37 -

Trường hợp tên của cột không bắt đầu bởi ký tự “@” và có chứa ký tự “/” khi đó tên của cột được hiểu như một đường dẫn tới giá trị của cột, bao gồm các phần tử cha và phần tử con có tên phân cách nhau bởi chính ký tự “/”. Để hiểu rõ hơn ta xem ví dụ sau:

Ví dụ 10:

SELECT P.ProductID "@ProductID", ProductName "@ProductName",

UnitPrice=ROUND(P.UnitPrice, 2), Quantity,

Discount=CONVERT(int, Discount * 100),

ExtendedPrice=ROUND(CONVERT(money, Quantity *(1 - Discount) *

P.UnitPrice), 2)

FROM Products P, [Order Details] Od

WHERE Od.ProductID = P.ProductID and Od.OrderID = 10248 FOR XML PATH

Kết quả như sau:

<row ProductID="11" ProductName="Queso Cabrales"> <UnitPrice>21.0000</UnitPrice>

<Quantity>12</Quantity> <Discount>0</Discount>

<ExtendedPrice>252.0000</ExtendedPrice> </row>

<row ProductID="42" ProductName="Singaporean Hokkien Fried Mee"> <UnitPrice>14.0000</UnitPrice>

<Quantity>10</Quantity> <Discount>0</Discount>

<ExtendedPrice>140.0000</ExtendedPrice> </row>

<row ProductID="72" ProductName="Mozzarella di Giovanni"> <UnitPrice>34.8000</UnitPrice>

<Quantity>5</Quantity> <Discount>0</Discount>

<ExtendedPrice>174.0000</ExtendedPrice> </row>

- 38 -

Trường hợp tên của cột có chứa ký tự “*” khi đó giá trị của cột được hiển thị trong tài liệu xml như một cột không có tên (nếu cột này không phải ở dạng xml) với nội dung là một nút. Ví dụ như sau:

Ví dụ 11:

SELECT P.ProductID "Product/ProductID", ProductName

"Product/ProductName", UnitPrice=ROUND(P.UnitPrice, 2), Quantity,

Discount=CONVERT(int, Discount * 100),

ExtendedPrice=ROUND(CONVERT(money, Quantity *(1 - Discount) *

P.UnitPrice), 2)

FROM Products P, [Order Details] Od

WHERE Od.ProductID = P.ProductID and Od.OrderID = 10248 FOR XML PATH

Kết quả như sau:

<row>

<Product>

<ProductID>11</ProductID>

<ProductName>Queso Cabrales</ProductName> </Product> <UnitPrice>21.0000</UnitPrice> <Quantity>12</Quantity> <Discount>0</Discount> <ExtendedPrice>252.0000</ExtendedPrice> </row> <row> <Product> <ProductID>42</ProductID>

<ProductName>Singaporean Hokkien Fried Mee</ProductName> </Product> <UnitPrice>14.0000</UnitPrice> <Quantity>10</Quantity> <Discount>0</Discount> <ExtendedPrice>140.0000</ExtendedPrice> </row> <row> <Product> <ProductID>72</ProductID>

<ProductName>Mozzarella di Giovanni</ProductName> </Product> <UnitPrice>34.8000</UnitPrice> <Quantity>5</Quantity> <Discount>0</Discount> <ExtendedPrice>174.0000</ExtendedPrice> </row>

- 39 -

Trường hợp tên của cột trùng với các lệnh trong Xpath thì sẽ tự động được ánh xạ sang các ký tự tương ứng, chẳng hạn khi dùng tên là “node()” thì sẽ được hiểu như khi tên cột là “*”, khi dùng tên cột là “comment()” thì giá trị của cột trả về được hiểu như một chú thích trong tài liệu xml, nếu kiểu của cột là xml thì sẽ nhận được một lỗi tương ứng trả về:

Ví dụ 12:

SELECT P.ProductID "ProductID", ProductName "*",

UnitPrice=ROUND(P.UnitPrice, 2), Quantity,

Discount=CONVERT(int, Discount * 100),

ExtendedPrice=ROUND(CONVERT(money, Quantity *(1 - Discount) *

P.UnitPrice), 2)

FROM Products P, [Order Details] Od

WHERE Od.ProductID = P.ProductID and Od.OrderID = 10248 FOR XML PATH

Kết quả như sau:

<row>

<ProductID>11</ProductID>Queso

Cabrales<UnitPrice>21.0000</UnitPrice><Quantity>12</Quantity><Discount

>0</Discount><ExtendedPrice>252.0000</ExtendedPrice></row> <row>

<ProductID>42</ProductID>Singaporean Hokkien Fried

Mee<UnitPrice>14.0000</UnitPrice><Quantity>10</Quantity><Discount>0</D iscount><ExtendedPrice>140.0000</ExtendedPrice></row>

<row>

<ProductID>72</ProductID>Mozzarella di

Giovanni<UnitPrice>34.8000</UnitPrice><Quantity>5</Quantity><Discount> 0</Discount><ExtendedPrice>174.0000</ExtendedPrice>

</row>

Ví dụ 13:

SELECT P.ProductID "node()", ProductName "comment()",

UnitPrice=ROUND(P.UnitPrice, 2), Quantity,

Discount=CONVERT(int, Discount * 100),

ExtendedPrice=ROUND(CONVERT(money, Quantity *(1 - Discount) *

P.UnitPrice), 2)

FROM Products P, [Order Details] Od

WHERE Od.ProductID = P.ProductID and Od.OrderID = 10248 FOR XML PATH

Kết quả như sau:

<row>11<!--Queso Cabrales--

><UnitPrice>21.0000</UnitPrice><Quantity>12</Quantity><Discount>0</Dis count><ExtendedPrice>252.0000</ExtendedPrice></row>

<row>42<!--Singaporean Hokkien Fried Mee--

><UnitPrice>14.0000</UnitPrice><Quantity>10</Quantity><Discount>0</Dis count><ExtendedPrice>140.0000</ExtendedPrice></row>

<row>72<!--Mozzarella di Giovanni--

><UnitPrice>34.8000</UnitPrice><Quantity>5</Quantity><Discount>0</Disc ount><ExtendedPrice>174.0000</ExtendedPrice></row>

- 40 -

Trong trường hợp sử dụng cấu trúc xml lồng nhau thì phải khai báo tên của cột là “data()” trong câu truy vấn được lồng bên trong nếu tên truyền vào cho Path bên trong là trống thì các phần tử bên truy vấn được lồng hiển thị dưới dạng dãy số, chẳng hạn:

Ngoài các cú pháp trên còn có một số câu lệnh đặc biệt, chẳng hạn để tài liệu xml không bị phân mảnh, người ta truyền thêm tham số ROOT(‘RootName’) vào sau câu truy vấn For xml, hoặc để thêm không gian tên cho tài liệu xml:

Ví dụ 14:

SELECT ShipName "@Shiper", ShipCity "@City", (SELECT OrderID AS "data()"

FROM Orders WHERE CustomerID = 'BOLID' FOR XML PATH('')) "@ID"

FROM Orders

FOR XML PATH('SHIPPINGINFO')

Kết quả như sau:

<SHIPPINGINFO Shiper="Vins et alcools Chevalier" City="Reims" ID="10326 10801 10970" />

<SHIPPINGINFO Shiper="Toms Spezialitäten" City="Münster" ID="10326 10801 10970" />

<SHIPPINGINFO Shiper="Hanari Carnes" City="Rio de Janeiro" ID="10326 10801 10970" />

<SHIPPINGINFO Shiper="Victuailles en stock" City="Lyon" ID="10326 10801 10970" />

- 41 -

Ngoài ra, đối với các dữ liệu tồn tại dưới dạng BINARY để hiện thị được trong tài liệu người ta phải mã hóa dữ liệu này, trong SQL cung cấp sẵn hàm mã hóa thành BASE64 cho các dữ liệu BINARY trong câu lệnh FOR XML, ta có ví dụ như sau:

Ví dụ 15:

SELECT CustomerID, ContactName, Country FROM Customers

WHERE Country = 'Spain'

FOR XML AUTO, ROOT('CustomersInfo') , ELEMENTS XSINIL

Kết quả như sau:

<CustomersInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Customers>

<CustomerID>BOLID</CustomerID>

<ContactName>Martín Sommer</ContactName> <Country>Spain</Country>

</Customers> <Customers>

<CustomerID>FISSA</CustomerID>

<ContactName>Diego Roel</ContactName> <Country>Spain</Country>

</Customers> <Customers>

<CustomerID>GALED</CustomerID>

<ContactName>Eduardo Saavedra</ContactName> <Country>Spain</Country>

</Customers> <Customers>

<CustomerID>GODOS</CustomerID>

<ContactName>José Pedro Freyre</ContactName> <Country>Spain</Country>

</Customers> <Customers>

<CustomerID>ROMEY</CustomerID>

<ContactName>Alejandra Camino</ContactName>

<Country>Spain</Country> </Customers>

</CustomersInfo>

Ví dụ 16:

Một phần của tài liệu NGHIÊN CỨU MỘT SỐ KỸ THUẬT KHAI PHÁ DỮ LIỆU XML ỨNG DỤNG TRONG THỰC HIỆN XỬ LÝ DỮ LIỆU QUAN HỆ (Trang 30 -43 )

×