发表于: 2008.06.08 23:47
分类: ORACLE
出处: http://yangtingkun.itpub.net/post/468/463985
---------------------------------------------------------------
描述延迟约束语句与DDL隐式提交。
小议延迟事务的提交(一):http://yangtingkun.itpub.net/post/468/463933
上一篇讨论了延迟约束提交的影响,这里再简单讨论一下延迟约束的一些其他特点:
SQL> TRUNCATE TABLE T;
表被截断。
SQL> INSERT INTO T VALUES (1, 'A');
已创建 1 行。
SQL> INSERT INTO T VALUES (2, 'B');
已创建 1 行。
SQL> COMMIT;
提交完成。
SQL> SET CONSTRAINTS ALL DEFERRED;
约束条件已设置。
SQL> INSERT INTO T VALUES (1, 'C');
已创建 1 行。
SQL> TRUNCATE TABLE T;
TRUNCATE TABLE T
*第 1 行出现错误:
ORA-02091: 事务处理已回退
ORA-00001: 违反唯一约束条件 (YANGTK.PK_T_ID)
SQL> SELECT * FROM T;
ID NAME
---------- ------------------------------
1 A
2 B
由于延迟约束的特点,COMMIT操作不再是一个肯定成功的操作,如果事务在提交时违反了约束,那么COMMIT就会报错。这就可能引发一个问题,带有隐式提交特性的DDL语句可能因为延迟约束的存在而失败,如上面的例子所示。失败发生在DDL语句之前的COMMIT处,因此例子中的TRUNCATE语句根本没有被执行。
SQL> CREATE TABLE T_LOG (LOGS VARCHAR2(30));
表已创建。
SQL> CREATE OR REPLACE TRIGGER TRI_BEFORE_TRUNCATE BEFORE TRUNCATE ON DATABASE
2 DECLARE
3 PRAGMA AUTONOMOUS_TRANSACTION;
4 BEGIN
5 INSERT INTO T_LOG VALUES ('BEFORE TRUNCATE');
6 COMMIT;
7 END;
8 /
触发器已创建
SQL> SELECT * FROM T;
ID NAME
---------- ------------------------------
1 A
2 B
SQL> SET CONSTRAINTS ALL DEFERRED;
约束条件已设置。
SQL> INSERT INTO T VALUES (1, 'C');
已创建 1 行。
SQL> TRUNCATE TABLE T;
TRUNCATE TABLE T
*第 1 行出现错误:
ORA-02091: 事务处理已回退
ORA-00001: 违反唯一约束条件 (YANGTK.PK_T_ID)
SQL> SELECT * FROM T_LOG;
未选定行
可以看到,这种DDL的错误连系统触发器都无法捕获,因为实际上DDL还没有执行,所以,采用延迟事务可能会给DDL执行失败的诊断造成一定的困难。
其实解决这个问题的方法就是在提交或执行DDL之前通过SET CONSTRAINTS ALL IMMEDIATE语句进行约束检查:
SQL> SET CONSTRAINTS ALL DEFERRED;
约束条件已设置。
SQL> INSERT INTO T VALUES (1, 'C');
已创建 1 行。
SQL> SET CONSTRAINTS ALL IMMEDIATE;
SET CONSTRAINTS ALL IMMEDIATE
*第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (YANGTK.PK_T_ID)
SQL> UPDATE T SET ID = 3 WHERE NAME = 'C';
已更新 1 行。
SQL> SET CONSTRAINTS ALL IMMEDIATE;
约束条件已设置。
SQL> TRUNCATE TABLE T;
表被截断。
SQL> SELECT * FROM T_LOG;
LOGS
------------------------------
BEFORE TRUNCATE











