DB2 9 引入 pureXML 技術,以解析後的分層格式原生存儲 XML,不再需「碎成關係表」或「存為 CLOB」。Java 開發者可沿用熟悉的 JDBC API,配合業界標準 SQL/XML (ISO 9075-14) 與 XQuery,無縫實現 XML 的增刪改查。本文基於 DB2 Developer Workbench (Eclipse 3.1 架構) 演示完整流程。
db2jcc.jar、db2jcc_javax.jar、db2jcc_license_cu.jar(位於 DB2_HOME/java/)com.ibm.db2.xml.demoCREATE TABLE clients (
id INT NOT NULL PRIMARY KEY,
name VARCHAR(50),
status VARCHAR(10), -- 'Gold', 'Silver'
contactinfo XML -- pureXML 列
);
範例 XML 文檔(存入 contactinfo):
<client>
<address>
<street>123 Main St</street>
<city>San Jose</city>
<state>CA</state>
<zip>95125</zip>
</address>
<phone type="work">408-555-1234</phone>
<phone type="home">408-555-5678</phone>
<email>edward.chen@example.com</email>
<email>e.chen@work.com</email>
</client>
package com.ibm.db2.xml.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DB2Conn {
private static final String URL = "jdbc:db2://localhost:50000/SAMPLE";
private static final String USER = "db2admin";
private static final String PASS = "password";
static {
try { Class.forName("com.ibm.db2.jcc.DB2Driver"); }
catch (ClassNotFoundException e) { throw new ExceptionInInitializerError(e); }
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(URL, USER, PASS);
}
}
public void insertXmlFromFile() throws SQLException, FileNotFoundException {
String sql = "INSERT INTO clients (id, name, status, contactinfo) VALUES (?, ?, ?, ?)";
try (Connection conn = DB2Conn.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
FileInputStream fis = new FileInputStream("data/client_1001.xml")) {
ps.setInt(1, 1001);
ps.setString(2, "Edward Chen");
ps.setString(3, "Gold");
// setBinaryStream 需指定流長度,或用 setBlob(conn.createBlob())
ps.setBinaryStream(4, fis, fis.available());
ps.executeUpdate();
}
}
進階:插入前可調用 XMLVALIDATE 針對已註冊 XML Schema 驗證,確保結構合規。
public void queryGoldClientsInZip(String zip) throws SQLException {
String sql = "SELECT name, " +
"XMLQUERY('$c/client/email[1]' PASSING contactinfo AS \"c\") AS first_email " +
"FROM clients " +
"WHERE status = ? " +
"AND XMLEXISTS('$c/client/address[zip = $z]' " +
" PASSING contactinfo AS \"c\", CAST(? AS VARCHAR(5)) AS \"z\")";
try (Connection conn = DB2Conn.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, "Gold");
ps.setString(2, zip);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
String name = rs.getString("name");
// XMLQUERY 返回 XML 序列,getString 會序列化為字符串(含標籤)
String emailXml = rs.getString("first_email");
System.out.printf("%s -> %s%n", name, emailXml);
}
}
}
}
// XQuery 不支援 JDBC 參數標記,必須包裝在 XMLQUERY/XMLTABLE 中
String xquery = "xquery for $c in db2-fn:xmlcolumn('CLIENTS.CONTACTINFO')/client " +
"where $c/address/zip = '95125' " +
"return $c/email[1]";
// 實際執行需用 Statement.executeQuery("VALUES XMLQUERY('" + xquery + "')"),不推薦生產使用
| 函數 | 用途 | 參數綁定 |
|---|---|---|
XMLEXISTS | WHERE 子句布爾判斷 | 支援 |
XMLQUERY | SELECT 列表提取標量/片段 | 支援 |
XMLTABLE | 將 XML 序列展開為虛擬表(可 JOIN) | 支援 |
XMLCAST | XML 值轉 SQL 類型 | 支援 |
UPDATE clients SET contactinfo = ? WHERE id = 1001;
-- IBM 提供遷移工具:Migrate XML Applications from DB2 8.x to DB2 Viper (developerWorks)
XMLQUERY/XMLEXISTS,自動處理命名空間與轉義XMLQUERY 提取標量,避免 SELECT contactinfo 全文檔回傳CREATE INDEX idx_zip ON clients(contactinfo) GENERATE KEYS USING XMLPATTERN '/client/address/zip' AS SQL VARCHAR(5)setBinaryStream/getBinaryStream 避免記憶體壓力DB2 9 pureXML 讓 Java 開發者以「熟悉的 JDBC + 標準 SQL/XML」駕馭原生 XML 存儲,無需學習新 API、無需 ORM 映射折騰。掌握 XMLQUERY/XMLEXISTS/XMLTABLE 三板斧,配合 XML 索引,即可在關係與文檔雙世界中游刃有餘。