EXECUTE IMMEDIATE 是 PL/SQL 中執行**動態 SQL** 的核心語句。它在運行時解析、編譯並執行字符串形式的 SQL 語句或 PL/SQL 塊,適用於:
EXECUTE IMMEDIATE dynamic_sql_string
[INTO {variable_list | record_variable}]
[USING [IN | OUT | IN OUT] bind_argument [, ...]]
[RETURNING INTO bind_argument [, ...]];
| 子句 | 用途 | 示例 |
|---|---|---|
| INTO | 單行查詢結果綁定到變量/記錄 | EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM '||v_tbl INTO v_cnt; |
| USING | 綁定輸入/輸出/輸入輸出參數 (防注入、性能) | EXECUTE IMMEDIATE 'DELETE FROM '||v_tbl||' WHERE id = :1' USING v_id; |
| RETURNING INTO | DML 返回值 (如序列值、更新後列) | EXECUTE IMMEDIATE 'INSERT INTO t VALUES (seq.NEXTVAL, :1) RETURNING id INTO :2' USING v_name RETURNING INTO v_new_id; |
CREATE OR REPLACE PROCEDURE drop_partition(p_table VARCHAR2, p_part VARCHAR2) IS
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE ' || p_table || ' DROP PARTITION ' || p_part;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -1418 THEN RAISE; END IF; -- 忽略分區不存在
END;
DECLARE
TYPE id_arr IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
v_ids id_arr;
BEGIN
SELECT id BULK COLLECT INTO v_ids FROM src_tbl WHERE ...;
FORALL i IN INDICES OF v_ids
EXECUTE IMMEDIATE 'DELETE FROM tgt_tbl WHERE id = :1' USING v_ids(i);
END;
-- ❌ 極度危險:字符串拼接,SQL 注入風險,硬解析風暴 EXECUTE IMMEDIATE 'SELECT * FROM ' || p_table || ' WHERE name = ''' || p_name || ''''; -- ✅ 安全、高性能:綁定變量,軟解析複用 EXECUTE IMMEDIATE 'SELECT * FROM ' || p_table || ' WHERE name = :1' USING p_name;
BEGIN
EXECUTE IMMEDIATE v_ddl;
EXCEPTION
WHEN OTHERS THEN
-- 記錄錯誤上下文
log_error('Dynamic DDL failed: ' || v_ddl, SQLCODE, SQLERRM);
-- 選擇性吞噬已知錯誤 (如 ORA-00942 表不存在, ORA-01418 分區不存在)
IF SQLCODE IN (-942, -1418) THEN NULL; ELSE RAISE; END IF;
END;
FORALL + 綁定數組,或靜態 SQL + 臨時表。EXECUTE IMMEDIATE 覆蓋 95%+ 需求。| 錯誤碼 | 含義 | 典型原因 |
|---|---|---|
| ORA-00900 | Invalid SQL statement | 動態字符串非合法 SQL (如空串、截斷) |
| ORA-01006 | Bind variable does not exist | USING 參數數量/順序與佔位符不匹配 |
| ORA-01008 | Not all variables bound | 佔位符多於 USING 參數 |
| ORA-06502 | Numeric or value error | INTO/RETURNING 目標變量類型/長度不匹配 |
| ORA-01476 | Divisor is equal to zero | 動態 SQL 內部邏輯錯誤 |
EXECUTE IMMEDIATE 是 PL/SQL 動態能力的基石。**牢記三條鐵律**:
1. **DDL/動態結構必用它**
2. **數值輸入永遠 USING 綁定** (安全+性能)
3. **異常處理要精準** (記錄上下文、選擇性吞噬已知錯誤)
掌握它,才能寫出靈活、安全、高性能的動態數據庫應用。