經過 5 年研發,DB2 9 (代號 Viper) 推出 pureXML 技術,以原生層次模型存儲 XML,避免 CLOB 文本或關係映射的效能與靈活性損耗。DB2 9 在同一資料列、同一張表中實現關係數據與 XML 數據的無縫融合,支援 SQL/XML (SQL + XQuery) 混合查詢,靈活索引加速 XML 檢索。本文基於 SAMPLE 資料庫 CUSTOMER 表,通過 JDBC Type 4 驅動完整演示 XML 插入、查詢 (XMLEXISTS/XMLQUERY/XMLTABLE)、更新、刪除操作,並附完整 Java 代碼範例。
| 類型 | 特點 | 代表 |
| Type 1 | JDBC-ODBC 橋接,依賴本地庫,可移植性差 | JDBC-ODBC Bridge |
| Type 2 | Java + 本地代碼,需部署 DB2 客戶端庫 | COM.ibm.db2.jdbc.app.DB2Driver |
| Type 3 | 純 Java 客戶端 + 中間件服務器 | COM.ibm.db2.jdbc.Net.DB2Driver |
| Type 4 | 純 Java,直連資料庫網絡協議 (推薦) | com.ibm.db2.jcc.DB2Driver (db2jcc.jar) |
2. 通用驅動連接範例
// 載入驅動
Class.forName("com.ibm.db2.jcc.DB2Driver");
// 連接 URL 格式
String url = "jdbc:db2://<host>:<port>/<db>";
// 例:jdbc:db2://localhost:50000/SAMPLE
// 屬性配置
Properties props = new Properties();
props.setProperty("user", "Administrator");
props.setProperty("password", "lys");
Connection conn = DriverManager.getConnection(url, props);
3. 外部屬性檔 (db2Conn.properties)
# JDBC 配置
hostName=localhost
portNumber=50000
databaseName=SAMPLE
userName=Administrator
passWord=lys
# XML 檔案路徑
fileName=F:\\eclipse\\WorkPlace\\DB2XML\\src\\p5.xml
4. 連接工具類 (db2Conn.java)
public class db2Conn {
public static Connection get(String db, String user, String pwd, String host, String port) {
Connection conn = null;
try {
Class.forName("com.ibm.db2.jcc.DB2Driver");
String databaseURL = "jdbc:db2://" + host + ":" + port + "/" + db;
Properties props = new Properties();
props.setProperty("user", user);
props.setProperty("password", pwd);
conn = DriverManager.getConnection(databaseURL, props);
if (conn == null) System.out.println("Connection Failed");
} catch (Exception e) { e.printStackTrace(); System.exit(-1); }
return conn;
}
}
三、XML 插入操作 (insertXML.java)
核心技巧:使用 PreparedStatement.setBinaryStream() 直接流式寫入 XML 文件,避免記憶體壓力。
public class Test2 {
public static void main(String[] args) throws Exception {
// 載入屬性檔、建立連接 (同上)
Connection conn = db2Conn.get(db, userName, passwd, host, port);
int id = 99; // PK,重複執行需修改或設自增
String fn = "F:\\eclipse\\WorkPlace\\DB2XML\\src\\Client8877.xml";
String sql = "INSERT INTO CUSTOMER (CID, INFO) VALUES (?, ?)";
File file = new File(fn);
PreparedStatement stmt = conn.prepareStatement(sql);
conn.setAutoCommit(true);
stmt.setInt(1, id);
stmt.setBinaryStream(2, new FileInputStream(file), (int) file.length());
if (stmt.executeUpdate() == 1)
System.out.println("Insert successful");
stmt.close();
conn.close();
}
}
四、XML 查詢操作 (readXML.java)
使用 ResultSet.getString() 直接獲取 XML 序列化字串,或 getBinaryStream() 流式讀取。
public static String getDescription(String cid) {
String desc = null;
try {
PreparedStatement stmt = conn.prepareStatement("SELECT INFO FROM CUSTOMER WHERE CID = ?");
stmt.setString(1, cid);
ResultSet rs = stmt.executeQuery();
if (rs.next()) desc = rs.getString(1);
else System.out.println("Customer not found");
rs.close(); stmt.close();
} catch (SQLException e) { /* 錯誤處理、回滾、退出 */ }
return desc;
}

五、進階 SQL/XML 查詢函數
1. XMLEXISTS —— 依 XML 內容過濾行
查找郵遞區號 95116 的客戶姓名:
SELECT NAME FROM CUSTOMER
WHERE XMLEXISTS('$c/Client/Address[Zip="95116"]' PASSING CUSTOMER.INFO AS "c")
$c/Client/Address[Zip="95116"]:XPath 表達式,$c 為上下文變數
PASSING INFO AS "c":將 XML 欄綁定到變數 $c
- 返回布林值,用於 WHERE 子句
2. XMLQUERY —— 投影單一 XML 元素值
列出狀態為 'good' 客戶的 Email:
SELECT XMLQUERY('$c/Client/Email' PASSING INFO AS "c") FROM CUSTOMER WHERE STATUS = 'good'
返回 XML 片段 (如 <Email>user@example.com</Email>)。
3. XMLTABLE —— 將 XML 節點映射為關係結果集
將 XML 多節點展開為多行多欄:
SELECT XT.* FROM CUSTOMER,
XMLTABLE('$c/Client/Phone' PASSING INFO AS "c"
COLUMNS
TYPE VARCHAR(10) PATH '@Type',
NUMBER VARCHAR(20) PATH '.'
) AS XT
產出關係表格,可直接 JOIN、聚合。
六、XML 更新操作
1. SQL UPDATE 方式 (需提供完整文檔)
UPDATE CLIENTS SET CONTACTINFO = XMLPARSE(DOCUMENT '<Email>new@email.com</Email>') WHERE ID = 3227
缺點:即使只改 Email,也需傳入完整 ContactInfo 文檔。
2. 系統存儲過程 XMLUPDATE (僅更新指定節點)
CALL DB2XMLFUNCTIONS.XMLUPDATE(?, ?, ?) -- 參數:表名、XPath、新值
優點:無需讀取/傳輸完整文檔,細粒度更新,效能優。
3. Java 完整更新範例 (updateXML.java 核心邏輯)
// 1. 查詢現有 XML 文檔
String xml = getProduct(pID); // 同查詢邏輯
// 2. 使用 DOM 解析並修改指定節點
Document doc = parse(xml);
setValue("/product/description/price/text()", "99.99"); // XPath 定位
// 3. 更新回資料庫
PreparedStatement stmt = conn.prepareStatement("UPDATE CUSTOMER SET INFO = ? WHERE CID = ?");
stmt.setString(1, serialize(doc));
stmt.setString(2, pID);
stmt.executeUpdate();
範例代碼採用 Apache Xerces DOM 實現,支援互動式選單修改多欄位。
七、XML 刪除操作
1. 刪除整行
DELETE FROM CUSTOMER WHERE CID = 1000
2. 依 XML 內容刪除 (配合 XMLEXISTS)
DELETE FROM CLIENTS
WHERE XMLEXISTS('$c/Client/Address[Zip="95116"]' PASSING CONTACTINFO AS "c")
八、最佳實踐總結
- Unicode 資料庫強制:僅 Unicode DB 支援 XML + 傳統類型混存
- Type 4 驅動首選:無需客戶端庫,部署簡單,效能佳
- 流式處理大 XML:
setBinaryStream/getBinaryStream 避免 OOM
- 細粒度更新用 XMLUPDATE:避免全文檔往返
- 混合查詢善用 XMLTABLE:將 XML 關係化,發揮 SQL 優化器優勢
- 索引策略:針對高頻 XPath 路徑建立 XML 索引,大幅提升 XMLEXISTS/XMLQUERY 效能
- Schema 演進無痛:無需 ALTER TABLE,新結構直接寫入,舊文檔兼容共存
DB2 9 pureXML 徹底消除了「關係或 XML」的二元對立,讓開發者在同一平台上以最適合的資料模型解決問題。立即下載 DB2 Express-C 體驗原生 XML 的威力!
- 上一篇文章: DB2 資料庫核心知識庫:從基礎語法到高階運維的完整速查手冊
- 下一篇文章: JDBC 連接不同版本 DB2 兼容性實測與最佳實踐指南
Copyright ©
程式碼之家 All Rights Reserved