首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> DB2 資料庫 >> DB2 教學

DB2 XML 編程實戰(二):在應用架構中靈活運用 pureXML 特性

     編輯:DB2 教學

前言:XML 從「邊緣」走向核心

過去兩年,XML 在數據庫中的定位發生了質變——不再是需「削足適履」融入關係模型的「臨時工」,而是成為一等公民。DB2 pureXML 讓 XML 保持層次結構,同時享受關係引擎的 ACID、索引、觸發器、約束等成熟能力。更有甚者,關係模型開始借鑑 XML 技術(如 JSON 支持)以獲取層次建模優勢。

DB2 混合存儲:關係與 XML 的最佳拍檔

DB2 允許在同一張表中同時存放關係列與 XML 列。XML 內部以解析後的樹結構存儲,邏輯上卻像 CLOB/BLOB 一樣佔據單一列。這極大簡化了模式設計:

CREATE TABLE CUSTOMER_TABLE (
  CUSTOMERID CHAR(12) NOT NULL,
  CUSTXML    XML NOT NULL,
  PRIMARY KEY (CUSTOMERID)
);

CREATE TABLE PURCHASE_TABLE (
  CUSTOMERID CHAR(12) NOT NULL,
  ITEMXML    XML NOT NULL,
  FOREIGN KEY (CUSTOMERID) REFERENCES CUSTOMER_TABLE(CUSTOMERID)
);

DB2 混合型存儲

插入數據與關係列無異:

INSERT INTO CUSTOMER_TABLE VALUES ('hardeep',
  '<Customer customerid="hardeep" firstname="hardeep" lastname="singh"/>');

Java 中亦同樣使用 PreparedStatement.setCharacterStream 寫入 XML 文件流。

DB2 混合型存儲邏輯視圖

查詢 XML:SQL/XML 與 XQuery 的無縫協作

展開 XML 列,模式從關係轉為層次。統一模式下,可用 XPath 定位 XML 內部節點。例如查找姓氏為 "singh" 的客戶:

SELECT CUSTXML FROM CUSTOMER_TABLE
WHERE XMLEXISTS('$cust/Customer[@lastname="singh"]' PASSING CUSTXML AS "cust");

參數化查詢(Java):

SELECT CUSTXML FROM CUSTOMER_TABLE
WHERE XMLEXISTS('$cust/Customer[@lastname=$lname]' 
  PASSING CUSTXML AS "cust", CAST(? AS VARCHAR(12)) AS "lname");

Viper 2 簡化了 PASSING 子句,可直接引用列名:

SELECT CUSTXML FROM CUSTOMER_TABLE
WHERE XMLEXISTS('$CUSTXML/Customer[@lastname=$lname]' 
  PASSING CAST(? AS VARCHAR(12)) AS "lname");

將業務邏輯下推至數據庫

XQuery 支持條件、循環、變量、函數、算術運算,且內建豐富 XSLT 映射能力,可在查詢中完成轉換。以合併客戶與購買記錄為例:

聯結兩個 XML 列

VALUES(XMLQUERY(
  'for $Customer in db2-fn:xmlcolumn("CUSTOMER_TABLE.CUSTXML")/Customer
   where $Customer/@customerid = $customerid
   return <Customer customerid="{$Customer/@customerid}"
                firstname="{$Customer/@firstname}"
                lastname="{$Customer/@lastname}">{
     for $Item in db2-fn:xmlcolumn("PURCHASE_TABLE.ITEMXML")/Customer
     where $Item/@customerid = $Customer/@customerid
     return $Item/Item
   }</Customer>'
  PASSING CAST(? AS VARCHAR(255)) AS "customerid"));

Viper 2 引入 XQuery Update,可直接在現有文檔插入節點,避免重構外層元素:

VALUES(XMLQUERY(
  'for $Customer in db2-fn:xmlcolumn("CUSTOMER_TABLE.CUSTXML")/Customer
   let $items := <Items>{
     for $Item in db2-fn:xmlcolumn("PURCHASE_TABLE.ITEMXML")/Customer
     where $Item/@customerid = $Customer/@customerid
     return $Item/Item
   }</Items>
   where $Customer/@customerid = $customerid
   return transform copy $cust := $Customer
          modify do insert $items as last into $cust
          return $cust'
  PASSING 'hardeep' AS "customerid"));

查詢結果

創建存儲過程封裝邏輯

CREATE PROCEDURE customerItems(IN custid VARCHAR(12))
DYNAMIC RESULT SETS 1 LANGUAGE SQL
BEGIN
  DECLARE c_cur CURSOR WITH RETURN FOR
    VALUES(XMLQUERY(... PASSING custid AS "customerid"));
  OPEN c_cur;
END

應用層代碼縮減為:

ResultSet rs = stmt.executeQuery("CALL customerItems(?)");
XMLParse xml = new XMLParse(rs.getString(1));

進階場景:動態保險費率計算

保險費率隨價格、日期變化,以 XML 形式從 Web Service 獲取:

<insurance>
  <rate price="100" currency="$" rate=".02"/>
  <rate price="500" currency="$" rate=".018"/>
  <rate price="" currency="$" rate=".015"/>
</insurance>

存儲過程接收 rate XML 參數,內部用 XQuery 條件表達式計算每筆訂單保費並插入結果 XML。這證明:XML 數據既可來自表列、函數生成,也可作為運行時參數傳入,數據庫與應用服務器的界限正在模糊。

關係與 XML 混合聯結

即使產品說明存放在關係表 SQLPRODUCT,仍可通過 XMLExists 聯結 XML 列:

SELECT details, weight FROM SQLPRODUCT, ITEM_TABLE
WHERE XMLEXISTS('$itemXML/item[@itemid=$pid]'
  PASSING ITEM_TABLE.ITEMXML AS "itemXML", SQLPRODUCT.PID AS "pid");

聯結關係列和 XML 列

Viper 2 允許向 XQuery 嵌入的 SQL 傳遞參數:

VALUES(XMLQUERY(
  'for $Item in db2-fn:xmlcolumn("PURCHASE_TABLE.ITEMXML")/Customer
   where $Item/@customerid = $custid
   return ($Item/Item,
     db2-fn:sqlquery(
       ''SELECT XMLROW(details, description, weight OPTION ROW "description")
          FROM sqlproduct WHERE pid = parameter(1)'',
       $Item/Item/@ID))'
  PASSING CAST(? AS VARCHAR(255)) AS "custid"));

性能優化手段

  • XML 索引:CREATE INDEX custfname ON customer_table(info) GENERATE KEY USING XMLPATTERN '/Customer/@firstname' AS SQL VARCHAR(64)
  • 模式簡化減少 JOIN
  • 查詢中過濾後再傳輸,降低 I/O
  • XMLTABLE 提取關鍵字段建關係索引
  • 全文搜索索引

結語

XML 已成行業標準。pureXML 讓數據庫原生支持索引、查詢、驗證、轉換、更新 XML。隨著更多邏輯下推,數據庫可直接發布存儲過程為 Web Service,成為 SOA 活躍節點。舊秩序已變,新秩序正在形成。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved