Oracle中DDL会隐式提交且不可回滚,需用自治事务隔离;自治事务须显式声明、提交或回滚,否则报ORA-06519;DDL权限、表空间配额及会话函数值均需特别注意。
存储过程中直接执行DDL会触发隐式提交
oracle 规定:任何 ddl 语句(如 create table、alter index、drop procedure)在执行时,会**自动触发 commit**,且无法被当前事务回滚。这意味着,如果你在存储过程里写 execute immediate 'create table t1 (id number)',哪怕前面刚做了 insert,这条 insert 也会被立即提交——你后续调用 rollback 对它无效。
自治事务(AUTONOMOUS_TRANSACTION)是唯一可行路径
想在存储过程中“安全”执行 DDL 并保持主事务独立,必须用自治事务。它会启动一个**完全独立的事务上下文**,有自己的 COMMIT/ROLLBACK,不影响外层逻辑。
- 必须在声明区显式加上
PRAGMA AUTONOMOUS_TRANSACTION; - 自治事务内执行的 DDL 仍会隐式提交,但只影响它自己,不污染调用方事务
- 自治事务结束后,必须显式调用
COMMIT或ROLLBACK,否则会报错ORA-06519: active autonomous transaction detected and rolled back
示例:
CREATE OR REPLACE PROCEDURE create_log_table(p_suffix VARCHAR2) AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE log_' || p_suffix || ' (msg VARCHAR2(100), ts TIMESTAMP DEFAULT SYSTIMESTAMP)';
COMMIT; -- 必须有
EXCEPTION
WHEN OTHERS THEN
ROLLBACK; -- 也必须有
RAISE;
END;DDL 执行失败时自治事务不会自动回滚
自治事务的异常处理和普通事务不同:ROLLBACK 不会自动发生,必须手动写。如果忘记 ROLLBACK,又没 COMMIT,Oracle 会在过程退出时强制回滚并抛出 ORA-06519。
- 所有 DDL 操作都应包裹在
BEGIN...EXCEPTION...END中 - 捕获
ORA-00955(对象已存在)、ORA-01031(权限不足)等常见错误 - 不要依赖“DDL 失败即事务终止”的直觉——自治事务必须显式收尾
权限与上下文切换容易被忽略
存储过程以定义者(definer's rights)模式运行,但 DDL 权限检查发生在**运行时**,且受当前会话权限影响。即使你用 GRANT CREATE TABLE TO myuser,如果该用户没有对目标表空间的 UNLIMITED TABLESPACE 或具体配额,CREATE TABLE 仍会失败。
- 确认用户有
CREATE TABLE、CREATE ANY TABLE(慎用)等系统权限 - 检查默认表空间配额:
SELECT tablespace_name, bytes/1024/1024 MB FROM dba_ts_quotas WHERE username = 'MYUSER'; - 避免在自治事务中依赖
SYSDATE或USER等会话级函数——它们取的是自治事务启动时的值,不是外层会话的
真正麻烦的不是语法,而是 DDL 的副作用:它改的是数据字典,影响整个实例的对象可见性与锁状态。哪怕成功执行,也可能阻塞其他会话对同名对象的访问几毫秒——这点在高并发存储过程调用中极易被低估。


















