EXECUTE IMMEDIATE 取代舊版 DBMS_SQL 套件,提供更簡潔、高效的動態 SQL/PLSQL 執行機制。本文系統整理 7 大核心用法與關鍵注意事項。
COMMIT;DDL 隱含提交前序交易INTO;多行需用暫存表或 REF CURSOREXCEPTION WHEN OTHERSBEGIN
EXECUTE IMMEDIATE 'SET ROLE ALL';
END;
/
DECLARE
l_depnam VARCHAR2(20) := 'TESTING';
l_loc VARCHAR2(10) := 'DUBAI';
BEGIN
EXECUTE IMMEDIATE 'INSERT INTO dept VALUES (:1, :2, :3)'
USING 50, l_depnam, l_loc;
COMMIT;
END;
/
位置標記法::1, :2, :3 對應 USING 順序;亦可用命名標記 :b1, :b2。
DECLARE
l_cnt VARCHAR2(20);
BEGIN
EXECUTE IMMEDIATE 'SELECT COUNT(1) FROM emp'
INTO l_cnt;
DBMS_OUTPUT.PUT_LINE(l_cnt);
END;
/
DECLARE
l_routin VARCHAR2(100) := 'gen2161.get_rowcnt';
l_tblnam VARCHAR2(20) := 'emp';
l_cnt NUMBER;
l_status VARCHAR2(200);
BEGIN
EXECUTE IMMEDIATE 'BEGIN ' || l_routin || '(:1, :2, :3); END;'
USING IN l_tblnam, OUT l_cnt, IN OUT l_status;
IF l_status != 'OK' THEN
DBMS_OUTPUT.PUT_LINE('ERROR: ' || l_status);
END IF;
END;
/
注意:參數模式必須顯式指定(IN 預設,OUT/IN OUT 必須寫出)。
DECLARE
TYPE empdtlrec IS RECORD (
empno NUMBER(4),
ename VARCHAR2(20),
deptno NUMBER(2)
);
empdtl empdtlrec;
BEGIN
EXECUTE IMMEDIATE 'SELECT empno, ename, deptno FROM emp WHERE empno = 7934'
INTO empdtl;
-- empdtl.empno, empdtl.ename, empdtl.deptno 可直接使用
END;
/
亦可使用 %ROWTYPE 簡化宣告。
DECLARE
l_dept PLS_INTEGER := 20;
l_dname VARCHAR2(20);
l_loc VARCHAR2(20);
BEGIN
EXECUTE IMMEDIATE 'SELECT dname, loc FROM dept WHERE deptno = :1'
INTO l_dname, l_loc
USING l_dept;
END;
/
順序固定:INTO 子句在前,USING 子句在後。
DECLARE
l_sal PLS_INTEGER := 2000;
BEGIN
EXECUTE IMMEDIATE 'INSERT INTO temp_table (empno, ename) ' ||
'SELECT empno, ename FROM emp WHERE sal > :1'
USING l_sal;
COMMIT;
-- 後續處理 temp_table 資料
END;
/
替代方案:使用 OPEN ref_cursor FOR dynamic_sql USING ... 實現真正的動態游標。
USING),**嚴禁**字串拼接使用者輸入DBMS_ASSERT.ENQUOTE_NAME 驗證DBMS_SQL 游標快取或 CURSOR_SHARINGFORALL + 集合綁定(需靜態 SQL)EXECUTE IMMEDIATE,組裝批次語句