使用 Oracle XQuery 查詢、構建和轉換 XML

idba發表於2008-08-21

在 Oracle 資料庫 10g 第 2 版中,Oracle 引入了一個與該資料庫整合的全功能自帶 XQuery 引擎,該引擎可用於完成與開發支援 XML 的應用程式相關的各種任務。XQuery 是一種用於處理 XML 資料模型的查詢語言,它實際上可操作任何型別的可用 XML 表達的資料。儘管 Oracle XQuery 實施使您可以使用資料庫資料和外部資料來源,但在處理資料庫中儲存的結構化資料方面,Oracle XML DB 通常可以顯著提高效能。

本文提供的示例不僅演示了在什麼場合下以及如何使用 XQuery 查詢、構建和轉換 XML,而且還演示瞭如何監控和分析 XQuery 表示式的效能執行,從而找到更高效的方法來處理同一工作負載。

基於關係資料構建 XML

在需要的情況下(例如,向 Web 服務傳送結果),您可能要基於關係資料構建 XML。要在 Oracle 資料庫 10g 第 2 版之前的版本中完成此任務,通常需要使用 SQL/XML 生成函式,如 XMLElement、XMLForest 和 XMLAgg()。在 Oracle 資料庫 10 g 第 2 版中,XQuery 將比這些函式更為高效。具體而言,在 XQuery 表示式內部使用 ora:view XQuery 函式,您可以查詢現有的關係表或檢視以及即時構建 XML,從而不必通過關係資料顯式建立 XML 檢視。列表 1 中的 PL/SQL 程式碼演示瞭如何使用 ora:view 基於示例資料庫模式 HR 的預設員工關係表中儲存的資料構建 XML 文件。

列表 1:使用 ora:view 基於關係資料建立 XML

BEGIN
IF(DBMS_XDB.CREATEFOLDER('/public/employees')) THEN
DBMS_OUTPUT.PUT_LINE('Folder is created');
ELSE
DBMS_OUTPUT.PUT_LINE('Cannot create folder');
END IF;
COMMIT;
END;
/

DECLARE
XMLdoc XMLType;
BEGIN
SELECT XMLQuery(
'for $j in 1
return (
   {
for $i in ora:view("HR", "employees")/ROW
where $i/EMPLOYEE_ID <= 102
return (
{xs:string($i/EMPLOYEE_ID)}
{xs:string($i/LAST_NAME)}
{xs:integer($i/SALARY)}
           )} )'
RETURNING CONTENT) INTO XMLdoc FROM DUAL;
IF(DBMS_XDB.CREATERESOURCE('/public/employees/employees.xml', XMLdoc)) THEN
DBMS_OUTPUT.PUT_LINE('Resource is created');
ELSE
DBMS_OUTPUT.PUT_LINE('Cannot create resource');
END IF;
COMMIT;
END;
/

在列表 1 中的第一個 PL/SQL 過程中,您只是在 XML 資訊庫中建立了一個新資料夾。在該資訊庫資料夾中,您隨後將儲存此處顯示的第二個 PL/SQL 過程中建立的 XML 文件。第二個 PL/SQL 過程首先發出 SELECT 語句,該語句使用 XMLQuery SQL 函式基於關係資料構建 XML。對於 XQuery 表示式(XMLQuery 在此處將其用作引數)而言,請注意巢狀的 FLWOR 表示式中使用的 ora:view XQuery 函式。在該示例中,ora:view 獲取兩個輸入引數,即“HR”和“employees”,它們指示該函式查詢屬於 HR 資料庫模式的員工表。因此,ora:view 將返回一個表示 HR.employees 錶行的員工 XML 文件序列。但為了節省結果文件中的空間,只將前三個員工記錄傳遞給結果序列。這是通過在 FLWOR 表示式的 where 子句中指定 $i/EMPLOYEE_ID <= 102 而實現的。請注意 FLWOR 表示式的 return 子句中使用的 xs:string()xs:integer() XQuery 型別表示式。實際上,此處使用的這兩個 XQuery 表示式不僅將 XML 節點值轉換為相應的型別,而且還將提取這些節點值。隨後,生成的員工 XML 文件作為 employees.xml 儲存到之前在列表 1 中另一個 PL/SQL 過程中建立的 /public/employees XML 資訊庫資料夾。要確保此操作已完成,可執行以下查詢:

SELECT XMLQuery('for $i in fn:doc("/public/employees/employees.xml")
return;
$i'
RETURNING CONTENT) AS RESULT FROM DUAL;

該查詢應生成以下輸出:


100
King
24000


101
Kochhar
17000


102
De Haan
17000


在以上 XQuery 中,fn:doc XQuery 函式用於訪問 Oracle XML DB 資訊庫中儲存的單個 XML 文件。但如果要處理一些具有相同或相似結構的 XML 文件(儲存在同一 XML 資訊庫資料夾中),應該怎麼做?這種情況下,另一個用於處理 XML 資訊庫資源的 XQuery 函式(即 fn:collection)可能會派上用場。本文稍後將介紹幾個有關如何使用 fn:collection XQuery 函式的示例。

查詢 XMLType 資料

XQuery 使您可以操作基於 XML 模式以及非基於模式的資料。以下示例演示瞭如何使用 XMLTable 函式從 OE 演示資料庫模式中查詢基於 PurchaseOrder XML 模式的 XMLType 表。

SELECT ttab.COLUMN_VALUE AS OrderTotal FROM purchaseorder,
XMLTable(
'for $i in /PurchaseOrder
where $i/User = "EABEL"
return;

{$i/Reference}

{fn:sum(for $j in $i/LineItems/LineItem/Part
return ($j/@Quantity*$j/@UnitPrice))}

'
PASSING OBJECT_VALUE
) ttab;

在以上示例中,您在 XMLTable 函式的 PASSING 子句中使用 OBJECT_VALUE 虛擬列將 purchaseorder 表作為上下文項傳遞給此處使用的 XQuery 表示式。XQuery 表示式計算使用者 EABEL 請求的每個購買訂單的總計,併為處理的每個訂單生成一個 OrderTotal XML 元素。要訪問生成的 XML,請使用 SELECT 列表中的 COLUMN_VALUE 虛擬列。最終的輸出應如下所示:

ORDERTOTAL
-------------------------------------------------------------

EABEL-20021009123338324PDT
1328.05


EABEL-20021009123335791PDT
2067.15


EABEL-20021009123336251PDT
289.6


EABEL-20021009123336382PDT
928.92

要獲得相同的最終結果,可以改用 XMLQuery 函式。但如果將上一個示例中使用的 XQuery 表示式引數傳遞給 XMLQuery(如下所示):

SELECT XMLQuery('for $i in /PurchaseOrder
where $i/User eq "EABEL"
return    
{$i/Reference}

{fn:sum(for $j in $i/LineItems/LineItem/Part
return ($j/@Quantity*$j/@UnitPrice))}

'
PASSING OBJECT_VALUE
RETURNING CONTENT)
FROM purchaseorder;

則 XQuery 表示式返回的空序列將與 purchaseorder 表聯接,從而包含在查詢總結果集中。實際上,這意味著輸出將不僅包含為使用者 EABEL 請求的訂單生成的 OrderTotal 元素,而且還包含為 purchaseorder 表中儲存的所有其他訂單生成的空行(預設情況下,purchaseorder 表包含 132 行)。從結果集中排除空行的方法之一是在 SELECT 語句的 WHERE 子句中使用 existsNode SQL 函式,而不是在 XQuery 表示式中使用 WHERE 子句,如下所示:

SELECT XMLQuery('for $i in /PurchaseOrder
return    
{$i/Reference}

{fn:sum(for $j in $i/LineItems/LineItem/Part
return ($j/@Quantity*$j/@UnitPrice))}

'
PASSING OBJECT_VALUE
RETURNING CONTENT) AS ordertotal
FROM purchaseorder
WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[User = "EABEL"]') = 1;

以上查詢與本部分開頭的 XMLTable 示例生成相同的輸出。

查詢 Oracle XML DB 資訊庫中的 XML 資料

為訪問 Oracle XML DB 資訊庫中儲存的 XML 資料,Oracle XQuery 引入了 fn:doc 和 fn:collection XQuery 函式。使用 fn:doc,您可以查詢 XML 資訊庫中儲存的單個 XML 文件,而 fn:collection 使您可以訪問同一資訊庫資料夾中儲存的多個 XML 文件。

正如本文之前(參閱使用關係資料構建 XML部分)介紹的示例所演示,使用 fn:doc 非常簡單直接。它獲取表示資訊庫檔案資源 (URI) 的字串並返回該 URI 指向的文件。要了解 fn:collection XQuery 函式的作用,同一資料夾中至少應有兩個資訊庫檔案。如果已經執行了列表 1 中的程式碼,則已經建立了 /public/employees 資訊庫資料夾並在其中儲存了 employees.xml 檔案。因此,您將需要在該資料夾中至少再建立一個 XML 檔案,然後才能試用 fn:collection。列表 2 中的 PL/SQL 程式碼基於 SCOTT/TIGER 演示資料庫模式的 dept 和 emp 表儲存的關係資料構建 XML,然後將生成的 XML 文件作為 acc_dept.xml 儲存到 /public/employees 資訊庫資料夾。要執行列表 2 中的 PL/SQL 過程,請確保以 SCOTT/TIGER 的身份登入。

列表 2:基於關係資料構建 XML 並將其儲存到 XML 資訊庫

DECLARE
XMLdoc XMLType;
BEGIN
SELECT XMLQuery(
'for $j in ora:view("SCOTT", "dept")/ROW
where $j/DEPTNO = 10
return ( 
{$j/DEPTNO,
$j/DNAME}
 {
for $i in ora:view("SCOTT", "emp")/ROW
where $i/DEPTNO = $j/DEPTNO
return (

{$i/EMPNO,
$i/ENAME,
$i/SAL}
)} 

)'
RETURNING CONTENT) INTO XMLdoc FROM DUAL;
IF(DBMS_XDB.CREATERESOURCE('/public/employees/acc_dept.xml', XMLdoc)) THEN
DBMS_OUTPUT.PUT_LINE('Resource is created');
ELSE
DBMS_OUTPUT.PUT_LINE('Cannot create resource');
END IF;
COMMIT;
END;
/

此時,/public/employees 資訊庫資料夾應包含兩個檔案:acc_dept.xml(由列表 2 中的 PL/SQL 程式碼生成)和 employees.xml 檔案(由列表 1 中的程式碼生成)。由於這些 XML 文件儲存在同一資訊庫資料夾中,因此可以使用 fn:collection 函式訪問兩個 XML 文件中儲存的員工資訊。然而,儘管這些 XML 文件均包含員工 XML 元素(這些元素實際上具有相同結構),但 XML 文件本身的結構迥然不同。在 employees.xml 中,文件根元素為 EMPLOYEES,而 acc_dept.xml 將 DEPARTMENT 用作根元素。要解決此問題,可以通過 XQuery 使用 XPath // 構造,從而導航到 XML 文件中的某個節點,而不必指定該節點的確切路徑。以下示例演示瞭如何在 XQuery 表示式中使用 XPath // 構造:

SELECT XMLQuery(
'for $i in fn:collection("/public/employees")//EMPLOYEE
where $i/SAL >= 5000
order by $i/ENAME
return;
$i'
RETURNING CONTENT) FROM DUAL;
該構造應生成以下輸出:
102
De Haan
17000


7839
KING
5000


100
King
24000


101
Kochhar
17000

您可以看到,以上輸出包含從 employees.xml 和 acc_dept.xml 中獲取的員工 XML 元素,這些元素表示薪酬大於或等於 5,000 美元的員工。

將 XML 分解為關係資料

如果應用程式處理關係資料而非 XML,而您需要訪問的資料以 XML 格式儲存,則將 XML 分解為關係資料可能會非常有用。繼續進行上一部分的示例,您可以使用 SQL 函式 XMLTable 將員工 XML 元素分解為虛擬表的單個列,如下所示:

SELECT emps.empno,emps.ename, emps.sal FROM 
XMLTable(
'for $i in fn:collection("/public/employees")//EMPLOYEE
where $i/SAL >= 5000
return;
$i'
COLUMNS empno NUMBER       PATH '/EMPLOYEE/EMPNO',
ename VARCHAR2(30) PATH '/EMPLOYEE/ENAME',
sal   NUMBER       PATH '/EMPLOYEE/SAL') emps;
該查詢將生成以下輸出:
EMPNO ENAME                 SAL
----- -------------- ----------
7839 KING                 5000
100 King                24000
101 Kochhar             17000
102 De Haan             17000

查詢外部資料來源

使用 XQuery,可以基於 XML 資料以及可以用 XML 表示的非 XML 資料生成 XML 文件,無論其位置如何:無論是儲存在資料庫中、置於網站上、即時建立還是儲存在檔案系統中。但要注意,Oracle XML DB 為針對資料庫中儲存的資料進行的 XML 操作提供了非常高的效能和可伸縮性。因此,如果您能夠完全控制所處理的資料,則最好將它移動到資料庫中。

正如您從前面的示例中瞭解到的,在 Oracle XQuery 實施中,doc 和 collection XQuery 函式用於訪問 Oracle XML DB 資訊庫中儲存的 XML 文件。可以通過 XMLTable 和 XMLQuery SQL 函式中的 PASSING 子句動態繫結外部資料來源。考慮以下示例。假設您的公司要為那些致力於 XQ 專案的員工支付獎金。因此,財務部發布了 empsbonus.xml 檔案,其中包含有資格獲得獎金的員工列表以及該列表中輸入的每個員工的獎金數額。empsbonus.xml 檔案可能如下所示:


100
1200


101
1000


在實際情況中,以上的 XML 檔案可能置於網站上(因此可以通過網際網路獲得)、以檔案形式儲存在本地檔案系統中,或以檔案資源形式儲存在 Oracle XML DB 資訊庫中。就本示例而言,該檔案位於網站上。為簡單起見,可以在目錄(Web 伺服器在其中儲存可從 Web 看到的文件)中建立一個員工資料夾,然後在該資料夾中插入 empsbonus.xml 檔案,以便可以通過以下 URL 訪問 empsbonus.xml 檔案:

http://localhost/employees/empsbonus.xml

接下來,假設您需要基於 empsbonus.xml 文件中儲存的資料建立一個報表。在該報表中,您可能不但要包含列表中顯示的獎金數額以及每個員工的員工 ID,還要包含他/她的全名。因此,可以首先使用以下查詢生成一個新的 XML 文件(假設您以 HR/HR 的身份連線):

SELECT XMLQuery(
'for $k in 1
return (
 {for $i in ora:view("employees")/ROW,
$j in $emps/EMPLOYEES/EMPLOYEE
where $i/EMPLOYEE_ID = $j/EMPNO
return (
{xs:string($i/EMPLOYEE_ID)}
{xs:string(fn:concat($i/FIRST_NAME, " ", $i/LAST_NAME))}
{xs:integer($j/BONUS)}
)} )'
PASSING xmlparse (document httpuritype
('http://localhost/employees/empsbonus.xml').getCLOB()) as "emps"
RETURNING CONTENT).getStringVal() as RESULT FROM DUAL;

以上查詢是一個有關如何使用 XQuery 基於 XML 和非 XML 資料(以不同的方式從不同的資料來源中檢索)生成 XML 文件的示例。具體而言,使用 ora:view() 函式訪問 HR 演示模式中的預設 employees 關係表,並使用 PASSING 子句中的 httpuritype() 函式借助於 HTTP 訪問 empsbonus.xml 文件。然後,在 FLWOR 表示式的 return 子句中構建新的 XML 文件。最後,將獲得以下 XML 文件:


100
Steven King
1200


101
Neena Kochhar
1000


解決效能問題

正如您從前面的部分中瞭解到的,XQuery 是一種用於查詢 Oracle 資料庫儲存的 XML 內容的高效方法 - 無論您是處理本地儲存的 XMLType 資料還是查詢基於關係資料構建的 XML 檢視。但根據對資料使用的儲存型別的不同,XQuery 表示式的執行效能可能迥然不同。尤其是,Oracle XML DB 可以優化基於由 ora:view 函式建立的 SQL/XML 檢視而構建的 XQuery 表示式。對於 XMLType 表或列中儲存的 XML 資料,只能對使用結構化(物件-關係)儲存技術儲存的基於 XML 模式的 XMLType 資料進行 XQuery 優化。

所選擇的儲存模型並非是影響 XQuery 表示式執行效能的唯一因素。在某些情況下,XQuery 表示式本身的結構也可能導致效能問題。要監控 XQuery 表示式的效能,可以列印並檢查關聯的 EXPLAIN PLAN。在 SQL*Plus 中,只需設定 AUTOTRACE 系統變數,即可列印 SQL 優化程式使用的執行路徑。但要執行該操作,請確保建立 PLUSTRACE 角色,然後將其授予連線到資料庫所使用的使用者。有關如何執行此操作的資訊,請參閱 Oracle 資料庫 10g 第 2 版 (10.2) 文件《SQL*Plus 使用者指南和參考》一書中的“調整 SQL*Plus”一章。以下示例演示瞭如何通過檢查 EXPLAIN PLAN 生成的執行計劃來獲得好處。假設您已經將 PLUSTRACE 角色授予預設使用者 OE,以 OE/OE 的身份登入並執行以下查詢:

SET AUTOTRACE ON EXPLAIN


SELECT count(*)
FROM oe.purchaseorder, XMLTable(
'for $i in /PurchaseOrder/User
where $i = "CJOHNSON"
return $i'
PASSING OBJECT_VALUE) ptab;
這將生成以下輸出:
COUNT(*)
----------
         9

Execution Plan
----------------------------------------------------
Plan hash value: 4046110317

----------------------------------------------------------------------------------------
| Id | Operation              | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|  0 | SELECT STATEMENT       |                 |     1 |  226  |   29  (0)  | 00:00:01 |

|  1 |  SORT AGGREGATE        |                 |     1 |  226  |            |          |

|  2 |   NESTED LOOPS         |                 | 10782 | 2379K |   29  (0)  | 00:00:01 |

|* 3 |   TABLE ACCESS FULL    | PURCHASEORDER   |     1 |  226  |    5  (0)  | 00:00:01 |

|  4 |   COLLECTION ITERATOR P| XMLSEQUENCEFROMX|       |       |            |          |


Predicate Information (identified by operation id):
---------------------------------------------------

3 - filter(SYS_CHECKACL("ACLOID","OWNERID",xmltype('

您可能對為以上查詢生成的執行計劃並不滿意。尤其是,所處理的行數可能非常大。由於 SQL 調整的主要目標是避免訪問對結果沒有任何影響的行,因此可能要繼續調整查詢以優化效能。對查詢中包含的 XPath 表示式進行重新建模後,可以再次重試它,如下所示:

SELECT count(*)
FROM oe.purchaseorder, XMLTable(
'for $i in /PurchaseOrder
where $i/User = "CJOHNSON"
return $i/User'
PASSING OBJECT_VALUE) ptab;
這次,輸出應如下所示:
COUNT(*)
----------
         9


Execution Plan
---------------------------------------------------
Plan hash value: 3411896580

----------------------------------------------------------------------------------------
| Id | Operation              | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|  0 | SELECT STATEMENT       |                 |     1 |   29  |   7   (0)  | 00:00:01 |

|  1 |  SORT AGGREGATE        |                 |     1 |   29  |            |          |

|  2 |   NESTED LOOPS         |                 |     1 |   29  |   7   (0)  | 00:00:01 |

|  3 |    FAST DUAL           |                 |     1 |       |   2   (0)  | 00:00:01 |

|* 4 |    TABLE ACCESS FULL   | PURCHASEORDER   |     1 |   29  |   5   (0)  | 00:00:01 |


Predicate Information (identified by operation id):
---------------------------------------------------

4 - filter("PURCHASEORDER"."SYS_NC00022$"='CJOHNSON' AND
SYS_CHECKACL("ACLOID","OWNERID",xmltype('

您可以看到,以上顯示的查詢生成相同的最終結果,但它們的執行計劃並不相同。檢視最後一個示例中的 XQuery 表示式,您可能會注意到它迭代頂層 PurchaseOrder 元素,其中的每個 PurchaseOrder 元素都表示基於 PurchaseOrder XMLType 模式的表中的一行。這意味著實際上重寫 XQuery 表示式,以迭帶基礎物件表(用於儲存分解的 PurchaseOrder 文件)中的行。與查詢要迭代不表示基礎表中的單個行的 XML 元素相比,該方法的效能更好一些。

但在某些情況下,很難發現 XQuery 表示式的哪個構造將使某些查詢的效能更好。這就是為什麼最好在開發階段使用調整工具的原因。

將動態變數繫結到 XQuery 表示式

另一種可以顯著提高 XQuery 表示式執行效能的技術是使用繫結動態變數。使用繫結變數(而不是將變數串聯為字串)可以使 Oracle 重用 SQL 語句,從而減少分析開銷並顯著提高應用程式的效能。可以在 XMLQuery 和 XMLTable SQL 函式中使用 PASSING 子句將動態變數繫結到 XQuery 表示式。該技術使您可以根據客戶端程式碼中計算的引數動態生成 XML。列表 3 中的示例演示瞭如何在從 PHP 指令碼執行的 XQuery 查詢中使用繫結變數。

列表 3:使用繫結變數

File:BindVars.php
$user = 'hr';
$pswd = 'hr';
$db ='(DESCRIPTION=
(ADDRESS_LIST=
(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))
          )
(CONNECT_DATA=(SID=orclR2)(SERVER=DEDICATED))
       )';
$empno=100;
$conn = oci_connect($user, $pswd, $db);
$sql = 'SELECT XMLQuery('."'".'for  $i in ora:view("employees")/ROW
where $i/EMPLOYEE_ID = $empno
return (
{$i/EMPLOYEE_ID,
$i/EMAIL,
$i/JOB_ID}
)'."'".'PASSING XMLElement("empno", :empno) AS "empno"
RETURNING CONTENT).GetStringVal() AS RESULT FROM DUAL';
$query = oci_parse($conn, $sql);
oci_bind_by_name($query, ":empno", $empno, 3);
oci_execute($query);
oci_fetch($query);
$str = oci_result($query, 'RESULT');
print $str;
?>
列表 3 中顯示的指令碼應生成以下輸出(注意,瀏覽器中可能不會顯示標記):
100
SKING
AD_PRES

XQuery 與 XSLT

儘管 Oracle 在 Oracle XML DB 中提供了一個自帶 XSLT 處理器,但在很多情況下(尤其是在處理大型文件時),XQuery 對於構建 XML 更高效。此外,XQuery 表示式通常比為同一作業設計的 XSLT 樣式表更具可讀性,並且更清楚。與 XSLT 一樣,XQuery 不但可用於將一個 XML 文件轉換為另一個 XML 文件,而且還可用於將 XML 轉換為另一種基於文字的格式,如 HTML 或 WML。

在本文前面的查詢 XMLType 資料部分中,您看到了一個有關使用 XQuery 將一個 XML 文件轉換為另一個 XML 文件的示例。具體而言,該示例使用 XQuery 表示式計算示例資料庫模式 OE 的 purchaseorder 表中儲存的訂單的訂單總計,然後為處理的每個訂單生成了一個 OrderTotal XML 元素。實際上,您可以使用 XSLT 執行相同操作。為此,您首先需要建立一個應用於 PurchaseOrder XML 文件的 XSLT 樣式表,以生成相應的 OrderTotal 元素。對於此示例,可以使用列表 4 中所示的 XSLT 樣式表。

列表 4:使用 XSLT 計算小計總和 (Quantity * UnitPrice)







 
 






為方便起見,您可能需要將此 XSL 樣式表儲存在資料庫中,然後再開始使用它。例如,您可以將樣式表作為檔案資源儲存在 Oracle XML DB 資訊庫中。執行該操作的方法之一是將樣式表作為檔案儲存到本地檔案系統中,然後使用以下某個網際網路協議將它移動到 XML 資訊庫:FTP、HTTP 或 WebDAV。假設您已經將列表 4 中的 XSLT 樣式表作為 orderTotal.xsl 儲存在 /public 資訊庫資料夾中,現在可以按以下示例所示將它用作 XMLTransform. SQL 函式的引數(假設您以 OE/OE 的身份登入):

SELECT XMLTRANSFORM(OBJECT_VALUE,
xdbUriType('/public/orderTotal.xsl').getXML()).GetStringVal() AS RESULT FROM
purchaseorder WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[User = "EABEL"]') = 1;

以上查詢將處理使用者 EABEL 請求的所有訂單(即儲存在 XMLType 的預設 PurchaseOrder 表中的訂單)並將生成與查詢 XMLType 資料部分中的 XQuery 查詢相同的輸出。

將列表 4 中的 orderTotal XSLT 樣式表與查詢 XMLType 資料部分中的示例使用的 XQuery 表示式進行比較,您可能會注意到,XQuery 方法要比 XSLT 方法更具吸引力。至少在使用 XQuery 時,您只需編寫很少的程式碼即可獲得相同的最終結果。

查詢 RSS 新聞提供

由於 RSS 新聞提供本質上是一個託管的 XML 檔案(RSS 新聞閱讀器從中獲取頭條新聞或其他內容),因此可以像處理任何其他可以通過 Web 獲得的 XML 文件那樣來處理它。正如您在本文前面的查詢外部資料來源部分中所見,可以使用 XQuery 查詢任何可以通過 URL 訪問的 XML。您通過 XMLTable 和 XMLQuery SQL 函式中的 PASSING 子句動態繫結所有外部 XML 資料來源。以下是一個查詢 RSS 新聞提供的 XQuery 示例:

SELECT XMLQuery(
'for  $i in $h//channel
return;

Recent OTN Headlines related to PHP technology
{$i/lastBuildDate}

{for $j in $h//item
where  ora:contains($j, "PHP")
return  {($j/title, $j/link)}}

'
PASSING xmlparse (document httpuritype
('http://www.oracle.com/technology/syndication/rss_otn_news.xml').getCLOB()) as "h"
RETURNING CONTENT).getStringVal() as RESULT FROM DUAL;

該 XQuery 應生成一個 XML 文件,其中包含 Oracle 技術網 (OTN) 最近釋出的與 PHP 技術相關的頭條新聞列表。所生成的 XML 文件可能如下所示:


Recent OTN Headlines related to PHP technology
Tue, 01 Nov 2005 19:37:42 GMT


Oracle Database 10g Express Edition:Free to Develop, Deploy, and Distribute
http://www.oracle.com/technology/xe


Explore the Oracle+PHP Cookbook
http://www.oracle.com/technology/pub/articles/oracle_php_cookbook


Download Zend Core for Oracle
http://www.oracle.com/technology/tech/php/zendcore/index.html



但在開發實際應用程式時,您將很可能需要 XQuery 表示式直接生成 HTML 標記,而不是僅僅生成一個如上所示的 XML 文件。這樣,您便可以構建一個更靈活、可維護性更高的應用程式,原因是在這種情況下,所有 RSS 處理(從提取必要的資料到將它包裝在 HTML 標記中)都將轉移到資料庫。這使您不必編寫負責 RSS 處理的應用程式程式碼。實際上這意味著您不必在諸如 RSS 新聞提供的結構已經更改的情況下修改應用程式程式碼。相反,您只需修改用於 RSS 處理的 XQuery 表示式。

總結

您已經在本文了解到,XQuery 是一個綜合的查詢語言,它提供了一種用於查詢、構建和轉換 XML 資料的高效方法。儘管 Oracle XQuery 實施使您可以操作任何可以用 XML 表示的資料(無論它儲存在資料庫中、位於網站上還是儲存在檔案系統中),但將處理的資料移動到資料庫中始終是一個不錯的主意。對於資料庫中儲存的資料,Oracle XML DB(對 XPath 重寫使用同一機制)只能顯著優化處理那些基於以下資料構建的 XQuery 表示式:這些資料包括關係資料、物件-關係資料或使用結構化(物件-關係)儲存技術儲存的基於 XML 模式的 XMLType 資料。

http://www.oracle.com/technology/global/cn/pub/articles/vasiliev_xquery.html

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1384/viewspace-432936/,如需轉載,請註明出處,否則將追究法律責任。

相關文章