觸發器完整架構解析
建立觸發器需包含六大核心要素:
| 要素 | 說明 | 範例值 |
| 觸發器名稱 | 唯一識別碼 | REORDER |
| 觸發事件 | 啟動操作類型 | INSERT / DELETE / UPDATE |
| 啟動時機 | 相對於事件執行順序 | BEFORE / AFTER |
| 執行粒度 | 作用範圍 | FOR EACH ROW / FOR EACH STATEMENT |
| 轉換變數 | 存取新舊資料 | OLD ROW / NEW ROW / OLD TABLE / NEW TABLE |
| 觸發條件 | WHEN 子句過濾 | 可包含子查詢與轉換變數 |
| 觸發本體 | 執行邏輯 | 一或多條 SQL 陳述式 |
實戰範例:庫存自動補貨觸發器
CREATE TRIGGER REORDER
AFTER UPDATE OF ON_HAND, MAX_STOCKED ON PARTS
REFERENCING NEW AS N_ROW
FOR EACH ROW MODE DB2SQL
WHEN (N_ROW.ON_HAND < 0.10 * N_ROW.MAX_STOCKED
AND N_ROW.ORDER_PENDING = 'N')
BEGIN ATOMIC
VALUES(ISSUE_SHIP_REQUEST(N_ROW.MAX_STOCKED - N_ROW.ON_HAND, N_ROW.PARTNO));
UPDATE PARTS SET ORDER_PENDING = 'Y' WHERE PARTNO = N_ROW.PARTNO;
END
存儲過程開發與 Java 調用實戰
Java 調用三步驟法
- 建立連線:
Class.forName("COM.ibm.db2.jdbc.net.DB2Driver").newInstance();
Connection con = DriverManager.getConnection(url, user, password);
- 註冊輸出參數:
CallableStatement cs = con.prepareCall("{call store_name(?,?,?)}");
cs.registerOutParameter(3, Types.INTEGER);
- 執行與取回結果:
cs.setString(1, "123");
cs.setString(2, "123");
cs.execute();
int result = cs.getInt(3);
完整調用範例
import java.sql.*;
public class TestProc {
public static void main(String[] args) {
String url = "jdbc:db2://wellhope/sample";
String user = "db2admin", password = "db2admin";
try (Connection con = DriverManager.getConnection(url, user, password);
CallableStatement cs = con.prepareCall("{call PRO_YHDL1(?,?,?)}")) {
cs.registerOutParameter(3, Types.INTEGER);
cs.setString(1, "123");
cs.setString(2, "123");
cs.execute();
System.out.println("執行結果: " + cs.getInt(3));
} catch (SQLException e) {
while (e != null) {
System.err.println("SQLState: " + e.getSQLState());
System.err.println("Message: " + e.getMessage());
System.err.println("ErrorCode: " + e.getErrorCode());
e = e.getNextException();
}
}
}
}
存儲過程實作範例(驗證使用者密碼)
import java.sql.*;
public class Pro_yhdl1 {
public static void pro_yhdl1(String m_id, String m_pwd, int[] result)
throws SQLException, Exception {
try (Connection con = DriverManager.getConnection("jdbc:default:connection");
PreparedStatement stmt = con.prepareStatement(
"SELECT PWD FROM DB2ADMIN.YHDL WHERE ID = ?")) {
stmt.setString(1, m_id.trim());
try (ResultSet rs = stmt.executeQuery()) {
String dbPwd = "";
if (rs.next()) dbPwd = rs.getString(1).trim();
result[0] = dbPwd.equals(m_pwd.trim()) ? 1 : 0;
}
}
}
}
JDBC 程式設計核心流程
- 載入驅動:
Class.forName("COM.ibm.db2.jdbc.net.DB2Driver")
- 建立連線:
DriverManager.getConnection(url)
- 建立 Statement:
con.createStatement()
- 執行查詢:
stmt.executeQuery("SQL")
- 處理結果集:
- 取得中繼資料:
rs.getMetaData()
- 欄位數:
rsmd.getColumnCount()
- 欄位值:
rsmd.getColumnLabel(i)
- 資源關閉:
stmt.close(), con.close()
常用 ResultSet 設定選項
setMaxRows(int):限制最大回傳列數
setQueryTimeout(int):設定查詢逾時秒數
setEscapeProcessing(boolean):控制逸出字元處理
CLI(Call Level Interface)架構特性
- 非新查詢語言,而是動態 SQL 的函式呼叫介面
- 應用程式首次執行時提交動態 SQL 給資料庫系統
- 函式可嵌入宿主語言(C/C++/COBOL 等)
- 與 JDBC 同屬動態 SQL 處理機制,但 CLI 更貼近底層
- 無需預編譯/聯編步驟,部署彈性高
開發選型建議
| 場景 | 推薦技術 | 理由 |
| Java 應用快速開發 | JDBC | 標準化、物件導向、生態豐富 |
| 高效能 C/C++ 系統 | CLI | 低延遲、精細控制、無 JVM 開銷 |
| 複雜業務邏輯封裝 | 存儲過程 | 減少網路往返、資料庫端優化 |
| 資料完整性強制約束 | 觸發器 | 自動化、不可繞過、集中維護 |