明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

Oracle XQuery查詢、構(gòu)建與轉(zhuǎn)換XML(1)

[摘要]在 Oracle 數(shù)據(jù)庫 10g 第 2 版中,Oracle 引入了一個(gè)與該數(shù)據(jù)庫集成的全功能自帶 XQuery 引擎,該引擎可用于完成與開發(fā)支持 XML 的應(yīng)用程序相關(guān)的各種任務(wù)。XQuery 是一種用于處理 XML 數(shù)據(jù)模型的查詢語言,它實(shí)際上可操作任何類型的可用 XML 表達(dá)的數(shù)據(jù)。盡管 O...
 

在 Oracle 數(shù)據(jù)庫 10g 第 2 版中,Oracle 引入了一個(gè)與該數(shù)據(jù)庫集成的全功能自帶 XQuery 引擎,該引擎可用于完成與開發(fā)支持 XML 的應(yīng)用程序相關(guān)的各種任務(wù)。XQuery 是一種用于處理 XML 數(shù)據(jù)模型的查詢語言,它實(shí)際上可操作任何類型的可用 XML 表達(dá)的數(shù)據(jù)。盡管 Oracle XQuery 實(shí)施使您可以使用數(shù)據(jù)庫數(shù)據(jù)和外部數(shù)據(jù)源,但在處理數(shù)據(jù)庫中存儲(chǔ)的結(jié)構(gòu)化數(shù)據(jù)方面,Oracle XML DB 通?梢燥@著提高性能。

本文提供的示例不僅演示了在什么場(chǎng)合下以及如何使用 XQuery 查詢、構(gòu)建和轉(zhuǎn)換 XML,而且還演示了如何監(jiān)控和分析 XQuery 表達(dá)式的性能執(zhí)行,從而找到更高效的方法來處理同一工作負(fù)載。

基于關(guān)系數(shù)據(jù)構(gòu)建 XML

在需要的情況下(例如,向 Web 服務(wù)發(fā)送結(jié)果),您可能要基于關(guān)系數(shù)據(jù)構(gòu)建 XML。要在 Oracle 數(shù)據(jù)庫 10g 第 2 版之前的版本中完成此任務(wù),通常需要使用 SQL/XML 生成函數(shù),如 XMLElement、XMLForest 和 XMLAgg()。在 Oracle 數(shù)據(jù)庫 10 g 第 2 版中,XQuery 將比這些函數(shù)更為高效。具體而言,在 XQuery 表達(dá)式內(nèi)部使用 ora:view XQuery 函數(shù),您可以查詢現(xiàn)有的關(guān)系表或視圖以及即時(shí)構(gòu)建 XML,從而不必通過關(guān)系數(shù)據(jù)顯式創(chuàng)建 XML 視圖。列表 1 中的 PL/SQL 代碼演示了如何使用 ora:view 基于示例數(shù)據(jù)庫模式 HR 的默認(rèn)員工關(guān)系表中存儲(chǔ)的數(shù)據(jù)構(gòu)建 XML 文檔。

列表 1:使用 ora:view 基于關(guān)系數(shù)據(jù)創(chuàng)建 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 中的第一個(gè) PL/SQL 過程中,您只是在 XML 信息庫中創(chuàng)建了一個(gè)新文件夾。在該信息庫文件夾中,您隨后將存儲(chǔ)此處顯示的第二個(gè) PL/SQL 過程中創(chuàng)建的 XML 文檔。第二個(gè) PL/SQL 過程首先發(fā)出 SELECT 語句,該語句使用 XMLQuery SQL 函數(shù)基于關(guān)系數(shù)據(jù)構(gòu)建 XML。對(duì)于 XQuery 表達(dá)式(XMLQuery 在此處將其用作參數(shù))而言,請(qǐng)注意嵌套的 FLWOR 表達(dá)式中使用的 ora:view XQuery 函數(shù)。在該示例中,ora:view 獲取兩個(gè)輸入?yún)?shù),即“HR”和“employees”,它們指示該函數(shù)查詢屬于 HR 數(shù)據(jù)庫模式的員工表。因此,ora:view 將返回一個(gè)表示 HR.employees 表行的員工 XML 文檔序列。但為了節(jié)省結(jié)果文檔中的空間,只將前三個(gè)員工記錄傳遞給結(jié)果序列。這是通過在 FLWOR 表達(dá)式的 where 子句中指定 $i/EMPLOYEE_ID <= 102 而實(shí)現(xiàn)的。請(qǐng)注意 FLWOR 表達(dá)式的 return 子句中使用的 xs:string()xs:integer() XQuery 類型表達(dá)式。實(shí)際上,此處使用的這兩個(gè) XQuery 表達(dá)式不僅將 XML 節(jié)點(diǎn)值轉(zhuǎn)換為相應(yīng)的類型,而且還將提取這些節(jié)點(diǎn)值。隨后,生成的員工 XML 文檔作為 employees.xml 保存到之前在列表 1 中另一個(gè) PL/SQL 過程中創(chuàng)建的 /public/employees XML 信息庫文件夾。要確保此操作已完成,可執(zhí)行以下查詢:

SELECT XMLQuery('for $i in fn:doc("/public/employees/employees.xml")

return;

$i'

RETURNING CONTENT) AS RESULT FROM DUAL;

該查詢應(yīng)生成以下輸出:





100

King

24000





101

Kochhar

17000





102

De Haan

17000



在以上 XQuery 中,fn:doc XQuery 函數(shù)用于訪問 Oracle XML DB 信息庫中存儲(chǔ)的單個(gè) XML 文檔。但如果要處理一些具有相同或相似結(jié)構(gòu)的 XML 文檔(存儲(chǔ)在同一 XML 信息庫文件夾中),應(yīng)該怎么做?這種情況下,另一個(gè)用于處理 XML 信息庫資源的 XQuery 函數(shù)(即 fn:collection)可能會(huì)派上用場(chǎng)。本文稍后將介紹幾個(gè)有關(guān)如何使用 fn:collection XQuery 函數(shù)的示例。

查詢 XMLType 數(shù)據(jù)

XQuery 使您可以操作基于 XML 模式以及非基于模式的數(shù)據(jù)。以下示例演示了如何使用 XMLTable 函數(shù)從 OE 演示數(shù)據(jù)庫模式中查詢基于 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 函數(shù)的 PASSING 子句中使用 OBJECT_VALUE 虛擬列將 purchaseorder 表作為上下文項(xiàng)傳遞給此處使用的 XQuery 表達(dá)式。XQuery 表達(dá)式計(jì)算用戶 EABEL 請(qǐng)求的每個(gè)購買訂單的總計(jì),并為處理的每個(gè)訂單生成一個(gè) OrderTotal XML 元素。要訪問生成的 XML,請(qǐng)使用 SELECT 列表中的 COLUMN_VALUE 虛擬列。最終的輸出應(yīng)如下所示:

ORDERTOTAL

-------------------------------------------------------------



EABEL-20021009123338324PDT

1328.05





EABEL-20021009123335791PDT

2067.15





EABEL-20021009123336251PDT

289.6





EABEL-20021009123336382PDT

928.92

要獲得相同的最終結(jié)果,可以改用 XMLQuery 函數(shù)。但如果將上一個(gè)示例中使用的 XQuery 表達(dá)式參數(shù)傳遞給 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 表達(dá)式返回的空序列將與 purchaseorder 表聯(lián)接,從而包含在查詢總結(jié)果集中。實(shí)際上,這意味著輸出將不僅包含為用戶 EABEL 請(qǐng)求的訂單生成的 OrderTotal 元素,而且還包含為 purchaseorder 表中存儲(chǔ)的所有其他訂單生成的空行(默認(rèn)情況下,purchaseorder 表包含 132 行)。從結(jié)果集中排除空行的方法之一是在 SELECT 語句的 WHERE 子句中使用 existsNode SQL 函數(shù),而不是在 XQuery 表達(dá)式中使用 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 示例生成相同的輸出。