Hãy khởi đầu nhanh chóng với DB2 9 pureXML, Phần 3: Truy vấn dữ liệu XML của DB2 bằng SQL

Bản phát hành DB2 9 của IBM mô tả sự hỗ trợ mới quan trọng để lưu trữ, quản lý và truy vấn dữ liệu XML, được gọi là pureXML. Trong bài này, hãy tìm hiểu cách truy vấn dữ liệu được lưu trữ trong các cột XML bằng cách sử dụng SQL và SQL/XML. Các bài viết tiếp theo trong loạt bài này sẽ minh họa cách truy vấn dữ liệu XML bằng XQuery, một ngôn ngữ mới được DB2 hỗ trợ.

Lưu ý: Được viết lần đầu vào năm 2006, bài viết này luôn được cập nhật để theo kịp với các thay đổi sản phẩm trong phiên bản 9.5 và 9.7 của DB2 .

Cynthia M. Saracco, Kiến trúc giải pháp cao cấp, IBM

Cynthia M. Saracco là kiến trúc sư giải pháp cao cấp tại Phòng thí nghiệm ở Thung lũng Silicon của IBM, bà chuyên về các công nghệ mới xuất hiện và các chủ đề quản lý cơ sở dữ liệu. Bà có 23 năm kinh nghiệm về công nghiệp phần mềm, đã viết 3 cuốn sách và hơn 60 tài liệu kỹ thuật và có 7 bằng sáng chế.



25 03 2010 (Xuất bản lần đầu tiên vào ngày 29 07 2011)

Mặc dù kiến trúc lai của DB2 biểu hiện một sự chuyển hướng quan trọng so với bản phát hành trước, việc tìm hiểu những khả năng XML mới của nó không phải là một quá trình tẻ nhạt. Nếu bạn đã quen với SQL, thì bạn có thể áp dụng ngay các kỹ năng của mình để làm việc với dữ liệu XML được lưu trữ nguyên gốc trong DB2. Hãy xem cách làm trong bài viết này.

Các tính năng XML trong DB2 9 bao gồm việc quản lý lưu trữ mới, lập chỉ mục và hỗ trợ ngôn ngữ truy vấn. Trong bài này, hãy tìm hiểu cách truy vấn dữ liệu trong các cột XML của DB2 bằng cách sử dụng SQL hoặc SQL với các phần mở rộng XML (SQL/XML). Các bài viết tiếp theo trong loạt bài này sẽ bàn về sự hỗ trợ mới của DB2 cho XQuery, một chuẩn công nghiệp mới nổi, và tìm hiểu khi nào nó có thể có ích nhất.

Bạn có thể ngạc nhiên khi biết DB2 cũng hỗ trợ các truy vấn song ngữ -- đó là, các truy vấn kết hợp các biểu thức trong cả hai SQL và XQuery. Ngôn ngữ (hoặc cách kết hợp các ngôn ngữ) nào mà bạn nên sử dụng phụ thuộc vào các yêu cầu ứng dụng của bạn, cũng như kỹ năng của bạn. Việc kết hợp các phần tử của cả hai ngôn ngữ truy vấn vào một truy vấn không khó như bạn tưởng. Và làm như vậy có thể cung cấp cho bạn các khả năng mạnh mẽ để tìm kiếm và tích hợp dữ liệu SQL truyền thống và dữ liệu XML.

Cơ sở dữ liệu mẫu

Các truy vấn trong bài viết này sẽ truy cập vào các bảng mẫu được tạo ra trong bài "Hãy khởi đầu nhanh chóng với DB2 9 pureXML, Phần 2" (developerWorks, 03. 2006). Nhìn lướt qua, các bảng mẫu "items" (các mặt hàng) và "clients" (các khách hàng) được định nghĩa như sau:

Liệt kê 1. Các định nghĩa bảng
create table items (
id 		int primary key not null, 
brandname 	varchar(30), 
itemname 	varchar(30), 
sku 		int, 
srp 		decimal(7,2), 
comments 	xml
)

create table clients(
id 		int primary key not null, 
name 		varchar(50), 
status 		varchar(10), 
contactinfo 	xml
)

Dữ liệu XML mẫu có trong cột "items.comments" được chỉ ra trong Liệt kê 2, trong khi dữ liệu XML mẫu trong cột "clients.contactinfo" được hiển thị trong Liệt kê 3. Các ví dụ truy vấn tiếp theo sẽ tham chiếu các phần tử cụ thể trong một hoặc cả hai tài liệu XML này.

Liệt kê 2. Tài liệu XML mẫu được lưu trữ trong cột "comments" của bảng "items"
<Comments>
	<Comment>
		<CommentID>133</CommentID>
		<ProductID>3926</ProductID>
		<CustomerID>8877</CustomerID>
		<Message>Heels on shoes wear out too quickly.</Message>
		<ResponseRequested>No</ResponseRequested>
	</Comment>
	<Comment>
		<CommentID>514</CommentID>
		<ProductID>3926</ProductID>
		<CustomerID>3227</CustomerID>
		<Message>Where can I find a supplier in San Jose?</Message>
		<ResponseRequested>Yes</ResponseRequested>
	</Comment>
</Comments>
Liệt kê 3. Tài liệu XML mẫu được lưu trữ trong cột "contactinfo" của bảng "clients"
<Client>
	<Address>
		<street>5401 Julio Ave.</street>
		<city>San Jose</city>
		<state>CA</state>
		<zip>95116</zip>
	</Address>
	<phone>
		<work>4084630000</work>
		<home>4081111111</home>
		<cell>4082222222</cell>
	</phone>
	<fax>4087776666</fax>
	<email>love2shop@yahoo.com</email>
</Cleint>

Môi trường truy vấn

Thiết kế tất cả các truy vấn trong bài viết này được ban hành tương tác với nhau, bạn có thể thực hiện qua bộ xử lý dòng lệnh DB2 hoặc Trình soạn thảo lệnh của DB2 (DB2 Command Editor) của Trung tâm điều khiển DB2 (DB2 Control Center). Các ảnh màn hình và các tập lệnh trong bài viết này tập trung vào cái sau. (IBM Data Studio và IBM Optim Development Studio cũng đi kèm với một bàn làm việc của Nhà phát triển dựa trên Eclipse có thể giúp các lập trình viên xây dựng các truy vấn bằng đồ họa. Tuy nhiên, bài viết này không bàn về các vấn đề phát triển ứng dụng hoặc Development Studio).

Để sử dụng DB2 Command Editor, hãy khởi chạy Control Center và chọn Tools > Command Editor. Một cửa sổ tương tự như Hình 1 sẽ xuất hiện. Gõ các truy vấn của bạn vào ô bên trên, nhấn vào mũi tên màu xanh lá cây ở góc trên bên trái để chạy chúng và xem kết quả của bạn ở ô bên dưới hoặc trong thẻ "Query results" (Các kết quả truy vấn) riêng.

Hình 1. DB2 Command Editor, có thể được khởi chạy từ DB2 Control Center
Ô phía trên cho thấy truy vấn SQL đơn giản. Ô phía dưới cho thấy truy vấn thành công.

Các truy vấn chỉ dùng SQL

Ngay cả khi hiểu biết của bạn về SQL bị hạn chế, bạn chỉ cần một chút nỗ lực để truy vấn dữ liệu XML. Ví dụ, truy vấn sau đây chọn tất cả các nội dung của bảng "clients", bao gồm thông tin XML được lưu trữ trong cột "contactinfo":

Liệt kê 4. Câu lệnh SELECT đơn giản
select * from clients

Tất nhiên, bạn có thể viết thêm nhiều truy vấn SQL có chọn lựa hơn kết hợp các phép chiếu và các phép hạn chế quan hệ. Truy vấn sau lấy ra các mã định danh ID, các tên và thông tin liên hệ cho tất cả khách hàng có trạng thái "Vàng" (Gold). Lưu ý rằng "contactinfo" chứa dữ liệu XML, trong khi hai cột khác không chứa:

Liệt kê 5. Câu lệnh SELECT đơn giản với phép chiếu và phép hạn chế
select id, name, contactinfo 
from clients
where status = 'Gold'

Và, như bạn có thể mong đợi, bạn có thể tạo các khung nhìn dựa trên các truy vấn như vậy, như đã thấy ở đây với "khung nhìn vàng":

Liệt kê 6. Tạo một khung nhìn có chứa một cột XML
create view goldview as 
select id, name, contactinfo 
from clients
where status = 'Gold'

Thật không may, có rất nhiều thứ mà bạn không thể làm được chỉ với SQL. Các câu lệnh SQL thuần túy cho phép bạn lấy toàn bộ các tài liệu XML (như bạn đã thấy), nhưng bạn không thể xác định các biến vị ngữ truy vấn dựa trên XML và bạn không thể lấy một phần các tài liệu XML hoặc các giá trị phần tử cụ thể từ một tài liệu XML. Nói cách khác, bạn không thể chiếu, hạn chế, nối, tổng hợp hoặc xếp thứ tự các đoạn của các tài liệu XML khi sử dụng SQL thuần túy. Ví dụ, bạn không thể lấy chỉ các địa chỉ email của các khách hàng Vàng của bạn hoặc các tên của các khách hàng sống trong vùng có mã vùng bưu điện "95116". Để biểu diễn các kiểu truy vấn này, bạn cần sử dụng SQL với các phần mở rộng XML (SQL/XML), XQuery hoặc kết hợp cả hai.

Phần tiếp theo tìm hiểu một số tính năng cơ bản của SQL/XML. Và trong một bài viết tiếp theo, hãy tìm hiểu cách viết XQuery cũng như cách kết hợp XQuery với SQL.


Các truy vấn SQL/XML

Như tên ngụ ý, SQL/XML được thiết kế làm cầu nối giữa thế giới SQL và XML. Nó đã phát triển như là một phần của nỗ lực tiêu chuẩn SQL và bây giờ bao gồm các đặc tả để nhúng các biểu thức XPath hoặc XQuery trong các câu lệnh SQL. XPath là một ngôn ngữ dùng để chuyển hướng các tài liệu XML để tìm các phần tử hay các thuộc tính. XQuery bao gồm sự hỗ trợ cho XPath.

Điều quan trọng cần lưu ý là các biểu thức XQuery (và XPath) phân biệt chữ hoa và chữ thường. Ví dụ, XQuery tham chiếu phần tử XML "zip" sẽ không áp dụng cho các phần tử XML có tên là "ZIP" hoặc "Zip". Đôi khi trường hợp phân biệt chữ hoa và chữ thường gây khó khăn cho các lập trình viên SQL phải nhớ, trong khi cú pháp truy vấn SQL cho phép họ sử dụng "zip", "ZIP" và "Zip" để nói đến cùng một tên cột.

DB2 9 mô tả nhiều hơn 15 hàm SQL/XML, cho phép bạn tìm kiếm dữ liệu cụ thể trong các tài liệu XML, chuyển đổi dữ liệu quan hệ thành dữ liệu XML, chuyển đổi dữ liệu XML thành dữ liệu quan hệ và thực hiện các nhiệm vụ có ích khác. Bài viết này không trình bày toàn bộ sự phong phú của SQL/XML. Tuy nhiên, nó xem xét một số thách thức truy vấn thông thường và làm thế nào để các hàm SQL/XML chủ yếu có thể giải quyết những thách thức này.

Các kết quả "hạn chế" dựa trên các giá trị phần tử XML

Các lập trình viên SQL thường viết các truy vấn để hạn chế các hàng được trả về từ DBMS dựa trên một số điều kiện. Ví dụ, truy vấn SQL trong Liệt kê 5 hạn chế các hàng được lấy từ bảng "clients" để chỉ bao gồm những khách hàng nào có trạng thái "Vàng". Trong trường hợp này, trạng thái của khách hàng được bắt giữ trong một cột SQL VARCHAR. Nhưng điều gì sẽ xảy ra nếu bạn muốn hạn chế việc tìm kiếm của mình dựa trên một số điều kiện áp dụng cho dữ liệu trong một cột XML? Hàm XMLExists của SQL/XML cung cấp một phương tiện để làm điều này.

XMLExists cho phép bạn chuyển hướng đến một phần tử trong tài liệu XML của bạn và thử nghiệm với một điều kiện cụ thể. Khi được quy định như một phần của mệnh đề WHERE, XMLExists hạn chế các kết quả trả về với chỉ các hàng nào có chứa một tài liệu XML có giá trị phần tử XML cụ thể (nói cách khác, ở đó giá trị cụ thể đánh giá là "đúng").

Hãy xem xét một vấn đề truy vấn mẫu đã nêu ở trên. Hãy tưởng tượng rằng bạn cần xác định vị trí các tên của tất cả các khách hàng sống trong vùng có một mã vùng bưu điện cụ thể. Nhớ lại, bảng "clients" lưu trữ các địa chỉ của các khách hàng (bao gồm các mã vùng bưu điện) trong một cột XML. (Xem Liệt kê 3.) Khi sử dụng XMLExists, bạn có thể tìm kiếm cột XML theo mã vùng bưu điện đích và hạn chế tập kết quả trả về cho phù hợp. Truy vấn SQL/XML sau đây trả về các tên của các khách hàng sống trong vùng có mã vùng bưu điện 95116:

Liệt kê 7. Hạn chế các kết quả dựa trên một giá trị phần tử XML
select name from clients
where xmlexists('$c/Client/Address[zip="95116"]'
passing clients.contactinfo as "c")

Dòng đầu tiên là một mệnh đề SQL quy định rằng bạn chỉ cần lấy thông tin trong cột "name" của bảng "clients". Mệnh đề WHERE gọi hàm XMLExists, quy định một biểu thức XPath nhắc DB2 chuyển hướng đến phần tử "zip" và kiểm tra một giá trị là 95116. Mệnh đề "$c/Client/Address" chỉ ra đường dẫn trong hệ thống phân cấp tài liệu XML ở nơi DB2 có thể xác định vị trí phần tử "zip". Khi sử dụng dữ liệu có khả năng truy cập từ nút "$c" (mà chúng tôi sẽ giải thích ngay), DB2 sẽ chuyển hướng thông qua phần tử "Client" (Khách hàng) đến phần tử con "Address" (Địa chỉ) của nó để kiểm tra mã vùng bưu điện (giá trị "zip"). Dòng cuối cùng giải quyết giá trị của "$c": đó là cột "contactinfo" của bảng "clients". Vì vậy, DB2 kiểm tra dữ liệu XML được chứa trong cột "contactinfo", chuyển hướng từ phần tử gốc "Client" đến phần tử con "Address" rồi tới "zip" và xác định xem khách hàng có sống trong vùng có mã vùng bưu điện đích không. Nếu có, hàm XMLExists đánh giá là "true" và DB2 trả về tên của khách hàng liên quan đến hàng đó.

Một lỗi phổ biến liên quan đến việc tạo biến vị ngữ truy vấn XMLExists, như trong Liệt kê 8.

Liệt kê 8. Cú pháp không đúng với việc hạn chế các kết quả dựa vào một giá trị phần tử XML
select name from clients
where xmlexists('$c/Client/Address/zip="95116" '
passing clients.contactinfo as "c")

Trong khi truy vấn này sẽ thực hiện thành công, nó sẽ không hạn chế các kết quả với các khách hàng đang sống trong vùng có mã bưu điện là 95116. (Điều này là do ngữ nghĩa được quy định trong tiêu chuẩn; nó không phải là duy nhất với DB2). Để hạn chế các kết quả với các khách hàng sống trong vùng có mã bưu điện là 95116, bạn cần sử dụng cú pháp được hiện thị trong Liệt kê 7.

Bạn có thể muốn biết cách đặt một truy vấn hạn chế dữ liệu XML trong một ứng dụng. Trong khi bài viết này không bàn về các chủ đề phát triển ứng dụng cụ thể, nó chỉ đưa ra một ví dụ Java đơn giản sử dụng một dấu tham số trong một câu lệnh SQL/XML để hạn chế kết quả theo thông tin về các khách hàng sống trong vùng có một mã vùng bưu điện cụ thể.

"Chiếu" các giá trị phần tử XML

Bây giờ hãy xem xét một tình huống hơi khác một chút, trong đó bạn muốn chiếu các giá trị XML vào tập kết quả trả về của bạn. Nói cách khác, chúng ta muốn lấy một hay nhiều giá trị phần tử từ các tài liệu XML của chúng ta. Có nhiều cách để làm điều này. Trước tiên hãy sử dụng hàm XMLQuery để lấy một giá trị cho một phần tử rồi sử dụng hàm XMLTable để lấy các giá trị cho nhiều phần tử và ánh xạ chúng vào các cột của một tập kết quả SQL.

Hãy xem xét cách giải quyết một vấn đề đã nêu ở trên: cách tạo ra một bản ghi liệt kê các địa chỉ email của khách hàng Vàng. Truy vấn sau đây trong Liệt kê 9 gọi hàm XMLQuery để hoàn thành nhiệm vụ này:

Liệt kê 9. Lấy thông tin email cho các khách hàng có đủ điều kiện
select xmlquery('$c/Client/email' 
passing contactinfo as "c") 
from clients 
where status = 'Gold'

Dòng đầu tiên quy định rằng bạn muốn trả về các giá trị cho phần tử con "email" của phần tử gốc "Client". Các dòng thứ hai và thứ ba cho thấy nơi DB2 có thể tìm thấy thông tin này -- trong cột "contactinfo" của bảng "clients". Dòng thứ tư bổ sung thêm cho truy vấn của bạn để cho biết rằng bạn chỉ quan tâm đến các địa chỉ email của các khách hàng Vàng. Truy vấn này sẽ trả về một tập các phần tử và các giá trị XML. Ví dụ, nếu bạn đã có 500 khách hàng Vàng, mỗi khách hàng có một địa chỉ email, kết quả đầu ra của bạn sẽ là một tập kết quả một cột có 500 hàng, như trong Liệt kê 10:

Liệt kê 10. Kết quả đầu ra mẫu của truy vấn trước đó
1
--------------------------------------------

<email>user5976@anyprovider.com</email>
. . . 
<email>someID@yahoo.com</email>

Nếu bạn có nhiều địa chỉ email của các khách hàng Vàng riêng biệt, bạn có thể muốn chỉ thị cho DB2 chỉ trả về địa chỉ chính (có nghĩa là, địa chỉ email đầu tiên được tìm thấy trong tài liệu "contactinfo" của khách hàng). Bạn có thể sửa đổi biểu thức XPath ở dòng đầu tiên của truy vấn của bạn để làm như vậy:

Liệt kê 11. Lấy địa chỉ email đầu tiên của từng khách hàng có đủ điều kiện
select xmlquery('$c/Client/email[1]' 
passing contactinfo as "c") 
from clients 
where status = 'Gold'

Cuối cùng, nếu bạn thiếu địa chỉ email của một số khách hàng Vàng, bạn có thể phải viết một truy vấn để loại trừ các kết quả bằng không (null) khỏi tập kết quả đó. Để thực hiện điều này, hãy sửa đổi truy vấn trước đó bằng cách thêm một biến vị ngữ khác vào mệnh đề WHERE để kiểm tra chỗ còn thiếu thông tin email. Bạn đã quen với hàm SQL/XML cho phép bạn làm điều đó -- đó là hàm XMLExists. Liệt kê 12 cho thấy cách bạn có thể viết lại truy vấn trước đó để lọc ra bất kỳ hàng nào có các khách hàng Vàng thiếu địa chỉ email trong thông tin liên hệ của họ (được lưu trữ như XML):

Liệt kê 12. Lấy địa chỉ email đầu tiên của mỗi khách hàng có đủ điều kiện mà ít nhất chúng ta có một địa chỉ email của họ
select xmlquery('$c/Client/email[1]' 
passing contactinfo as "c") 
from clients 
where status = 'Gold'
and xmlexists('$c/Client/email' passing contactinfo as "c")

Bây giờ hãy xem xét một tình huống hơi khác một chút, trong đó bạn cần lấy nhiều giá trị phần tử XML. Hàm XMLTable tạo ra kết quả dạng bảng từ dữ liệu được lưu trữ trong các cột XML và khá có ích để cung cấp cho các lập trình viên một khung nhìn "quan hệ" của dữ liệu XML. Giống như XMLExistsXMLQuery, hàm XMLTable làm cho DB2 chuyển hướng qua hệ thống phân cấp tài liệu XML để định vị dữ liệu quan tâm. Tuy nhiên, hàm XMLTable cũng bao gồm các mệnh đề để ánh xạ dữ liệu XML đích vào các cột của tập kết quả của các kiểu dữ liệu SQL.

Hãy xem xét truy vấn sau đây (Liệt kê 13), nó chiếu các cột của cả dữ liệu quan hệ lẫn dữ liệu XML được lưu trữ trong bảng "items". (Xem Liệt kê 2 để xem xét lại bảng "items"). Các mã định danh ý kiến, các mã định danh khách hàng và các thông báo được lưu trữ trong các tài liệu XML trong cột "comments". Các tên mặt hàng được lưu trữ trong cột VARCHAR của SQL.

Liệt kê 13. Lấy nhiều phần tử XML và chuyển đổi mỗi phần tử đó thành một kiểu dữ liệu SQL truyền thống
select t.Comment#, i.itemname, t.CustomerID, Message from items i, 
xmltable('$c/Comments/Comment' passing i.comments as "c"
columns Comment# integer path 'CommentID',
	CustomerID integer path 'CustomerID',
	Message varchar(100) path 'Message') as t

Dòng đầu tiên quy định các cột có trong tập kết quả của bạn. Các cột được bao quanh bằng các dấu ngoặc kép và được thêm tiền tố với biến "t" dựa vào các giá trị phần tử XML, như các dòng truy vấn tiếp theo cho biết. Dòng thứ hai gọi hàm XMLTable để xác định cột XML của DB2 chứa dữ liệu đích ("i.comments") và đường dẫn trong các tài liệu XML của cột nơi mà các phần tử cần quan tâm được định vị (trong phần tử con "Comment" của phần tử gốc "Comments"). Mệnh đề "columns", bao trùm các dòng từ 3 đến 5, nhận biết các phần tử XML cụ thể sẽ được ánh xạ vào các cột kết quả đầu ra trong tập kết quả SQL, đã quy định trên dòng 1. Phần của ánh xạ này có quy định các kiểu dữ liệu mà các giá trị của phần tử XML sẽ được chuyển đổi theo các kiểu dữ liệu đó. Trong ví dụ này, tất cả dữ liệu XML được chuyển đổi theo kiểu dữ liệu SQL truyền thống.

Hình 2 cho thấy các kết quả mẫu khi chạy truy vấn này. Như bạn thấy, đầu ra là một tập kết quả SQL đơn giản. Lưu ý rằng các tên cột đã được chuyển thành chữ hoa -- một sự kiện thông thường với SQL.

Hình 2. Kết quả đầu ra mẫu từ truy vấn khi sử dụng hàm XMLTABLE
Màn hình các kết quả truy vấn cho thấy bốn cột dữ liệu

Nếu muốn, bạn có thể sử dụng hàm XMLTable để tạo ra các tập kết quả cũng có các cột XML. Ví dụ, câu lệnh sau đây tạo ra một tập kết quả tương tự tập kết quả trước đó, trừ dữ liệu "Message" được chứa trong một cột XML chứ không phải cột VARCHAR của SQL.

Liệt kê 14. Lấy nhiều phần tử XML và chuyển đổi chúng sang các kiểu dữ liệu SQL truyền thống hoặc dữ liệu XML
select t.Comment#, i.itemname, t.CustomerID, Message from items i, 
xmltable('$c/Comments/Comment' passing i.comments as "c"
columns Comment# integer path 'CommentID',
	CustomerID integer path 'CustomerID',
	Message XML by ref path 'Message') as t

Tạo các khung nhìn quan hệ của dữ liệu XML

Như bạn có thể tưởng tượng, các hàm SQL/XML có thể được sử dụng để định nghĩa các khung nhìn. Điều này đặc biệt có ích nếu bạn muốn đưa cho các lập trình viên ứng dụng SQL của bạn một mô hình quan hệ về dữ liệu XML nguyên gốc của bạn.

Việc tạo ra một khung nhìn quan hệ trên dữ liệu trong một cột XML không phức tạp hơn nhiều so với việc chiếu các giá trị phần tử XML. Bạn chỉ cần viết một câu lệnh SQL/XML SELECT gọi hàm XMLTable và sử dụng hàm này làm cơ sở cho định nghĩa khung nhìn của bạn. Ví dụ sau đây trong Liệt kê 15 tạo ra một khung nhìn dựa vào thông tin trong các cột XML và không- XML của bảng "items". (Nó tương tự như truy vấn trong Liệt kê 13.)

Liệt kê 15. Tạo ra một khung nhìn, dựa vào kết quả đầu ra của XMLTABLE
create view commentview(itemID, itemname, commentID, message, mustrespond) as 
select i.id, i.itemname, t.CommentID, t.Message, t.ResponseRequested from items i, 
xmltable('$c/Comments/Comment' passing i.comments as "c"
columns CommentID integer path 'CommentID',
	Message varchar(100) path 'Message',
	ResponseRequested varchar(100) path 'ResponseRequested') as t;

Mặc dù rất dễ tạo ra các khung nhìn quan hệ trên dữ liệu cột XML, bạn nên xem xét cẩn thận cách sử dụng chúng nếu bạn không dùng phiên bản V9.7. Trước phiên bản V9.7, DB2 đã không sử dụng các chỉ mục cột XML khi đã đưa ra các truy vấn dựa vào các khung nhìn như vậy. Vì thế, nếu bạn đã lập chỉ mục cho phần tử ResponseRequested và đã đưa ra một truy vấn SQL hạn chế các kết quả của cột "mustrespond" theo một giá trị nhất định, thì DB2 sẽ đọc tất cả các tài liệu XML và tìm kiếm giá trị "ResponseRequested" thích hợp. Điều này sẽ làm chậm hiệu năng thời gian chạy, trừ khi bạn có ít dữ liệu. Vì vậy, hãy cẩn thận ở đây cho đến khi bạn nâng cấp lên phiên bản V9.7, khi DB2 sẽ sử dụng các chỉ mục XML dựa vào các biến vị ngữ SQL.

Nối dữ liệu XML và dữ liệu quan hệ

Đến bây giờ, bạn có thể tự hỏi về việc nối dữ liệu XML với dữ liệu không-XML (ví dụ, dữ liệu quan hệ dựa trên các kiểu SQL truyền thống). DB2 cho phép bạn làm điều này bằng một câu lệnh SQL/XML đơn. Trong khi có những cách khác để tạo nên các kết nối như vậy, tùy thuộc vào lược đồ cơ sở dữ liệu của bạn và các yêu cầu khối lượng công việc, chúng ta sẽ trình bày một ví dụ ở đây. Và bạn có thể ngạc nhiên khi biết rằng bạn đã biết đủ về SQL/XML để nhận làm việc này.

Hãy nhớ lại rằng cột XML trong bảng "items" có chứa một phần tử "CustomerID". Cột này có thể dùng làm một khóa nối cho cột "id" dựa trên-số nguyên trong bảng "clients". Vì vậy, nếu bạn muốn có một bản ghi các tên và trạng thái các khách hàng đã góp ý kiến về một hoặc nhiều sản phẩm của bạn, bạn sẽ phải nối các giá trị phần tử XML từ một bảng có các giá trị số nguyên SQL tới bảng khác. Và một cách để thực hiện việc này là sử dụng hàm XMLExists, như trong Liệt kê 16:

Liệt kê 16. Nối dữ liệu XML và dữ liệu không-XML
select clients.name, clients.status from items, clients
where xmlexists('$c/Comments/Comment[CustomerID=$p]'
passing items.comments as "c", clients.id as "p")

Dòng đầu tiên xác định các cột SQL có trong tập kết quả truy vấn và các bảng nguồn được tham chiếu trong truy vấn. Dòng thứ hai có mệnh đề kết nối của bạn. Ở đây, hàm XMLExists xác định xem giá trị "CustomerID" trong một nguồn đích có bằng một giá trị lấy ra từ một nguồn đích khác không. Dòng thứ ba quy định các nguồn này: nguồn đầu tiên là cột XML "comments" trong bảng "items" và nguồn thứ hai là cột "id" số nguyên trong bảng "clients". Như vậy, nếu các khách hàng đã góp ý kiến về mặt hàng bất kỳ và thông tin về khách hàng này có sẵn trong bảng "clients", thì biểu thức XMLExists sẽ đánh giá là "true" (đúng) và tên và thông tin trạng thái của khách hàng sẽ có trong bản ghi đó.

Sử dụng biểu thức "FLWOR" trong SQL/XML

Mặc dù chúng ta đã chỉ thảo luận một vài hàm, SQL/XML cung cấp nhiều khả năng mạnh mẽ để truy vấn dữ liệu XML và tích hợp dữ liệu đó với dữ liệu quan hệ. Thật vậy, bạn đã thấy một số ví dụ về cách làm điều đó, nhưng chúng ta sẽ bàn một thêm một chút nữa ở đây.

Cả hai hàm XMLExistsXMLQuery đều cho phép bạn kết hợp XQuery vào SQL. Ví dụ trước của chúng ta cho biết cách sử dụng các hàm này với các biểu thức XPath đơn giản để chuyển hướng đến một phần của một tài liệu XML cần quan tâm. Bây giờ hãy xem xét một ví dụ đơn giản trong đó bạn bao gồm XQuery trong các truy vấn SQL của mình.

XQueries có thể chứa một số hoặc tất cả các mệnh đề sau: "for," "let," "where," "order by" và "return." Nhìn chung, chúng tạo thành các biểu thức FLWOR (được đọc như từ flower). Các lập trình viên SQL có thể nhận thấy thật là thuận tiện để kết hợp các XQuery vào các danh sách SELECT của họ để trích xuất (hoặc chiếu) các đoạn của các tài liệu XML vào các tập kết quả của họ. Và trong khi đây không phải là cách duy nhất có thể sử dụng hàm XMLQuery, thì nó là một kịch bản mà bài viết này trình bày. (Một bài viết sau trong loạt bài này sẽ bàn sâu hơn về XQuery).

Hãy tưởng tượng rằng bạn muốn lấy các tên và các địa chỉ email chính của các khách hàng "Vàng" của bạn. Theo một số khía cạnh, nhiệm vụ này tương tự như một nhiệm vụ mà chúng ta đã thực hiện ở trên (xem Liệt kê 11), khi chúng ta tìm hiểu cách chiếu các giá trị phần tử XML. Ở đây, bạn chuyển qua XQuery (bằng các mệnh đề "for" và "return") làm đầu vào cho hàm XMLQuery :

Liệt kê 17. Lấy dữ liệu XML bằng cách sử dụng các mệnh đề "for" và "return" của XQuery
select name, xmlquery('for $e in $c/Client/email[1] return $e' 
passing contactinfo as "c") 
from clients
where status = 'Gold'

Dòng đầu tiên quy định rằng các tên khách hàng và kết quả đầu ra từ hàm XMLQuery sẽ được chứa trong tập kết quả. Dòng thứ hai cho biết rằng phần tử con "email" đầu tiên của phần tử "Client" là được trả về. Dòng thứ ba nhận biết nguồn dữ liệu XML của chúng ta -- cột "contactinfo". Dòng 4 cho chúng ta biết cột này nằm trong bảng "clients". Cuối cùng, dòng thứ năm cho biết rằng chỉ có các khách hàng "Vàng" cần được chúng ta quan tâm.

Vì ví dụ này rất đơn giản, bạn có thể viết truy vấn tương tự ở đây. Để thay thế, bạn có thể viết truy vấn tương tự theo cách gọn hơn nhiều so với cách bạn đã làm ở trên:

Liệt kê 18. Viết lại truy vấn ở trên theo một cách gọn hơn
select name, xmlquery('$c/Client/email[1]' 
passing contactinfo as "c") 
from clients
where status = 'Gold'

Tuy nhiên, mệnh đề return của XQuery cho phép bạn chuyển đổi kết quả đầu ra XML khi cần. Ví dụ, bạn có thể trích xuất các giá trị phần tử email và xuất bản các giá trị này dưới dạng HTML. Truy vấn sau đây sẽ tạo ra một tập kết quả trong đó địa chỉ email đầu tiên của mỗi khách hàng Vàng được trả về như là một đoạn HTML.

Liệt kê 19. Lấy và chuyển đổi dữ liệu XML thành HTML
select xmlquery('for $e in $c/Client/email[1]/text() 
return <p>{$e}</p>' 
passing contactinfo as "c") 
from clients
where status = 'Gold'

Dòng đầu tiên cho biết bạn đã quan tâm đến việc biểu diễn văn bản của địa chỉ email đầu tiên của các khách hàng có đủ điều kiện. Dòng thứ hai quy định rằng thông tin này được bao quanh bằng các thẻ của đoạn HTML trước khi trả về. Cụ thể là, các dấu móc nhọn ( { } ) chỉ thị cho DB2 đánh giá biểu thức kèm theo (trong trường hợp, "$e") thay vì xử lý nó như là một chuỗi bằng chữ. Nếu bạn bỏ qua các dấu móc nhọn đó, DB2 sẽ trả về một tập kết quả có chứa "<p>$e</p>" cho mọi bản ghi khách hàng có đủ điều kiện.

Xuất bản dữ liệu quan hệ như dữ liệu XML

Cho đến nay, chúng ta đã tập trung vào các cách để truy vấn, trích xuất hoặc chuyển đổi dữ liệu chứa trong một cột XML của DB2. Và, như bạn đã thấy, các khả năng này đều có sẵn thông qua SQL/XML.

SQL/XML cũng cung cấp các tính năng tiện dụng khác. Trong số đó là khả năng chuyển đổi hoặc xuất bản dữ liệu quan hệ như là dữ liệu XML. Bài viết này chỉ trình bày ba hàm SQL/XML liên quan sau: XMLElement, XMLAggXMLForest.

Hàm XMLElement cho phép bạn chuyển đổi dữ liệu được lưu giữ trong các cột SQL truyền thống thành các đoạn XML. Do đó, bạn có thể xây dựng các phần tử XML (có hoặc không có các thuộc tính XML) từ cơ sở dữ liệu SQL của mình. Ví dụ sau đây lồng thêm cách sử dụng hàm XMLElement của nó để tạo ra một loạt các phần tử mặt hàng, mỗi phần tử lại chứa các phần tử con cho các giá trị mã định danh ID, tên thương hiệu và mã hàng trong kho ("sku") thu được từ bảng "items":

Liệt kê 20. Sử dụng hàm XMLElement để xuất bản dữ liệu quan hệ như dữ liệu XML
select xmlelement (name "item", 
	xmlelement (name "id", id), 
	xmlelement (name "brand", brandname), 
	xmlelement (name "sku", sku) ) from items 
where srp < 100

Chạy truy vấn này sẽ tạo ra một kết quả tương tự như:

Liệt kê 21. Kết quả đầu ra mẫu từ truy vấn trước đó
<item>
  <id>4272</id>
  <brand>Classy</brand>
  <sku>981140</sku>
</item>
. . . 
<item>
  <id>1193</id>
  <brand>Natural</brand>
  <sku>557813</sku>
</item>

Bạn có thể kết hợp hàm XMLElement với các hàm xuất bản SQL/XML để xây dựng và nhóm các giá trị XML với nhau, lồng chúng vào các hệ thống phân cấp như mong muốn. Ví dụ trong Liệt kê 22 sử dụng hàm XMLElement để tạo các phần tử customerList mà nội dung của chúng được nhóm lại theo các giá trị trong cột "status" (trạng thái). Đối với mỗi bản ghi "customerList", hàm XMLAgg trả về một chuỗi các phần tử khách hàng, mỗi chuỗi gồm các phần tử con dựa vào cột "name" và "status" của chúng ta. Hơn nữa, bạn sẽ thấy rằng các giá trị phần tử khách hàng được sắp xếp thứ tự theo tên của khách hàng.

Liệt kê 22. Tổng hợp và nhóm dữ liệu
select xmlelement(name "customerList",
xmlagg (xmlelement (name "customer", 
xmlforest (name as "fullName", status as "status") )
order by name ) )
from clients 
group by status

Hãy giả sử bảng "clients" của chúng ta chứa ba giá trị "trạng thái" riêng: "Gold" (Vàng), "Silver" (Bạc) và "Standard" (Chuẩn). Việc chạy truy vấn trước đó sẽ làm cho DB2 trả về ba phần tử customerList, mỗi phần tử có thể chứa nhiều phần tử con khách hàng để chứa thêm tên và thông tin trạng thái. Vì vậy, kết quả đầu ra sẽ xuất hiện tương tự như:

Liệt kê 23. Kết quả đầu ra mẫu từ truy vấn trước đó
<customerList>
  <customer>
    <fullName>Chris Bontempo</fullname>
    <status>Gold</status>
  </customer>
  <customer>
    <fullName>Ella Kimpton</fullName> 
    <status>Gold</status>
  </customer>
. . . 
</customerList>
<customerList>
  <customer>
    <fullName>Lisa Hansen</fullName>
    <status>Silver</status>
  </customer>
. . .
</customerList>
<customerList>
  <customer>
    <fullName>Rita Gomez</fullName>
    <status>Standard</status>
  </customer>
. . .
</customerList>

Các hoạt động cập nhật và xóa

Mặc dù trọng tâm của bài viết này là về tìm kiếm và lấy ra dữ liệu được lưu trữ trong các cột XML bằng cách sử dụng SQL, nhưng cũng đáng bỏ chút thời gian xem xét hai nhiệm vụ phổ biến khác: đó là cập nhật và xoá dữ liệu trong các cột XML.

DB2 9 cho phép những người dùng cập nhật và xóa dữ liệu XML bằng các câu lệnh SQL và SQL/XML. Thật vậy, vì dự thảo ban đầu của tiêu chuẩn XQuery không đề cập đến những vấn đề này, nên những người dùng của DB2 đã phải dựa vào SQL để thực hiện các nhiệm vụ này. Tuy nhiên, W3C đã đang tiếp tục đưa vào một Phương tiện cập nhật XQuery (XQuery Update Facility), được triển khai thực hiện trong DB2 phiên bản 9.5. Việc bổ sung XQuery Update Facility (ban đầu gọi là TRANSFORM-PHÉP BIẾN ĐỔI) đã làm đơn giản hóa đáng kể việc cập nhật các thuộc tính và các phần tử trong một tài liệu XML, cũng như đã thiết lập một tiêu chuẩn để làm điều đó. Bây giờ XQuery Update Facility hiện đang trong Trạng thái giới thiệu ứng cử viên (Candidate Recommendation Status).

Cập nhật dữ liệu XML

Trong khi DB2 9 cho phép bạn cập nhật một cột XML bằng một câu lệnh UPDATE của SQL hoặc thông qua việc sử dụng một thủ tục đã lưu do hệ thống cung cấp (DB2XMLFUNCTIONS.XMLUPDATE), với DB2 phiên bản 9.5, có thể sử dụng XQuery Update Facility mới. Điều này cho phép cập nhật, chèn, xóa và tạo một phần tử hoặc thuộc tính mới trong một tài liệu XML hiện có mà không cần tạo lại toàn bộ tài liệu. Phương tiện Cập nhật cũng có thể được sử dụng để sửa đổi nhiều nút trong giao dịch tương tự.

Ví dụ, nếu bạn muốn ban hành một câu lệnh UPDATE để thay đổi địa chỉ e-mail về thông tin liên hệ của một khách hàng cụ thể, thì bạn đơn giản phải cung cấp địa chỉ e-mail mới.

Hãy xem xét câu lệnh sau đây:

Liệt kê 24. Câu lệnh UPDATE mẫu
update clients
set contactinfo = xmlquery( '
          copy $new := $CONTACTINFO
          modify do replace value of $new/client/email with "newemail@someplace.com"
          return  $new' ) 
where id = 3227;

Các mệnh đề của phương tiện XQuery Update yêu cầu "copy $new", "modify do replace of $new" và "return $new". Bạn có thể tìm hiểu thêm về cú pháp chính xác và các tùy chọn trong phần Tài nguyên dưới đây. Chúng tôi đã đưa cả trang web với các đặc tả XQuery cũng như một bài viết của developerWorks cung cấp thêm chi tiết về XQuery Update Facility (Phương tiện cập nhật XQuery).

Xóa dữ liệu XML

Xóa các hàng chứa các cột XML là một quá trình đơn giản. Câu lệnh DELETE của SQL cho phép bạn nhận biết (hoặc hạn chế) các hàng bạn muốn xóa thông qua một mệnh đề WHERE. Mệnh đề này có thể có các biến vị ngữ đơn giản để nhận biết các giá trị các cột không-XML hoặc các hàm SQL/XML để nhận biết các giá trị phần tử XML được chứa trong các cột XML.

Ví dụ, đây là cách bạn có thể xóa tất cả các thông tin khách hàng có mã định danh khách hàng 3227:

Liệt kê 25. Xóa dữ liệu của một khách hàng cụ thể
delete from clients 
where id = 3227

Bạn có nhớ cách hạn chế các câu lệnh SELECT của SQL để trả về chỉ các hàng của các khách hàng sống trong vùng có mã bưu điện 95116 không? Nếu có, bạn có thể dễ dàng áp dụng hiểu biết đó để xóa các hàng theo dõi các khách hàng đó. Đây là cách để làm điều này bằng hàm XMLExists:

Liệt kê 26. Xóa dữ liệu của các khách hàng trong một mã vùng cụ thểe
delete from clients
where xmlexists('$c/Client/Address[zip="95116"]'
passing clients.contactinfo as "c");

Lập chỉ mục

Cuối cùng, cần lưu ý rằng bạn có thể tạo các chỉ mục XML chuyên dụng để tăng tốc truy cập dữ liệu được lưu trữ trong các cột XML. Vì đây là một bài viết giới thiệu và dữ liệu mẫu nhỏ, nên bài viết này không trình bày chủ đề đó ở đây. Tuy nhiên, trong các môi trường sản xuất, việc định nghĩa các chỉ mục phù hợp có thể rất quan trọng để đạt được hiệu năng tối ưu. Phần Tài nguyên của bài viết này có thể giúp bạn tìm hiểu thêm về công nghệ lập chỉ mục mới của DB2.


Tóm tắt

Bài viết này đã trình bày nhiều về nền tảng, làm nổi bật một số khía cạnh quan trọng của SQL/XML và cách bạn có thể sử dụng nó để truy vấn dữ liệu trong các cột XML. Chắc chắn có nhiều thứ mà bạn có thể làm với các hàm SQL và SQL/XML hơn những thứ mà chúng ta đã thảo luận ở đây. Bài viết này bao gồm một ví dụ Java đơn giản để minh họa cách bạn có thể sử dụng các dấu tham số với SQL/XML để truy vấn dữ liệu trong các cột XML. Chúng ta sẽ thảo luận các vấn đề phát triển ứng dụng chi tiết hơn trong một bài viết tương lai. Tuy nhiên, bài viết tiếp theo sẽ tìm hiểu một số khía cạnh thú vị về XQuery, một ngôn ngữ truy vấn mới được DB2 9 hỗ trợ.

Lời cảm ơn

Cảm ơn George Lapis, Matthias Nicola, Sriram Padmanabhan, Gary Robinson, Hardeep Singh, và Bert Van der Linden vì sự giúp đỡ của họ cho bài viết này.

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

  • Xây dựng dự án phát triển tiếp theo của bạn bằng phần mềm dùng thử của IBM, có sẵn để tải trực tiếp từ developerWorks.
  • Bây giờ bạn có thể sử dụng DB2 miễn phí. Hãy tải về DB2 Express-C, một phiên bản miễn phí của Ấn bản DB2 Express cho cộng đồng, cung cấp các tính năng dữ liệu cốt lõi giống như Ấn bản DB2 Express và cung cấp một cơ sở vững chắc để xây dựng và triển khai các ứng dụng.

Thảo luận

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=Information Management
ArticleID=749762
ArticleTitle=Hãy khởi đầu nhanh chóng với DB2 9 pureXML, Phần 3: Truy vấn dữ liệu XML của DB2 bằng SQL
publish-date=03252010