发表于: 2008.06.09 23:46
分类: ORACLE
出处: http://yangtingkun.itpub.net/post/468/464069
---------------------------------------------------------------
描述事务与SET CONSTRAINTS语句的关系。
小议延迟事务的提交(一):http://yangtingkun.itpub.net/post/468/463933
小议延迟事务的提交(二):http://yangtingkun.itpub.net/post/468/463985
上面一篇讨论了延迟事务对DDL隐式提交的影响,这里简单讨论一下事务与设置延迟约束的关系。
首先设置延迟约束的语句不必是事务中的第一条语句:
SQL> SELECT * FROM T;
未选定行
SQL> INSERT INTO T VALUES (1, 'A');
已创建 1 行。
SQL> SET CONSTRAINTS ALL DEFERRED;
约束条件已设置。
SQL> INSERT INTO T VALUES (1, 'B');
已创建 1 行。
这个例子中,在事务开始后执行了SELECT和INSERT,然后启用了延迟约束。
第二,延迟约束在事务提交或回滚后自动恢复到非延迟状态:
SQL> UPDATE T SET ID = ROWNUM;
已更新2行。
SQL> COMMIT;
提交完成。
SQL> INSERT INTO T VALUES (1, 'C');
INSERT INTO T VALUES (1, 'C')
*第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (YANGTK.PK_T_ID)
SQL> SET CONSTRAINTS ALL DEFERRED;
约束条件已设置。
SQL> INSERT INTO T VALUES (1, 'C');
已创建 1 行。
SQL> ROLLBACK;
回退已完成。
SQL> INSERT INTO T VALUES (1, 'C');
INSERT INTO T VALUES (1, 'C')
*第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (YANGTK.PK_T_ID)
第三,回滚到一个保存点并不能使得延迟约束回滚到当时的状态:
SQL> SELECT * FROM T;
ID NAME
---------- ------------------------------
1 A
2 B
SQL> INSERT INTO T VALUES (3, 'C');
已创建 1 行。
SQL> SET CONSTRAINTS ALL DEFERRED;
约束条件已设置。
SQL> INSERT INTO T VALUES (1, 'D');
已创建 1 行。
SQL> SAVEPOINT A;
保存点已创建。
SQL> INSERT INTO T VALUES (1, 'E');
已创建 1 行。
SQL> UPDATE T SET ID = ROWNUM;
已更新5行。
SQL> SET CONSTRAINTS ALL IMMEDIATE;
约束条件已设置。
SQL> INSERT INTO T VALUES (6, 'F');
已创建 1 行。
SQL> ROLLBACK TO A;
回退已完成。
SQL> SELECT * FROM T;
ID NAME
---------- ------------------------------
1 A
2 B
3 C
1 D
SQL> INSERT INTO T VALUES (1, 'E');
INSERT INTO T VALUES (1, 'E')
*第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (YANGTK.PK_T_ID)
SQL> COMMIT;
COMMIT
*第 1 行出现错误:
ORA-02091: 事务处理已回退
ORA-00001: 违反唯一约束条件 (YANGTK.PK_T_ID)
可以看到,虽然回滚到保存点A,但是在保存点A是的延迟约束状态已经不存在了,因此,再插入相同的ID就会导致错误。不过虽然这时不是延迟约束状态,但是已经插入的重复ID并不会报错,只有在提交的时候才会报错。
从上面的几个例子可以看出,延迟约束只是一种状态,可以随时通过SET CONSTRAINTS语句进行设置。而延迟约束状态在事务提交、回滚或发出SET CONSTRAINTS ALL IMMEDIATE语句时结束。
在看最后一个例子:
SQL> SELECT * FROM T;
ID NAME
---------- ------------------------------
1 A
2 B
SQL> INSERT INTO T VALUES (3, 'C');
已创建 1 行。
SQL> SET CONSTRAINTS ALL DEFERRED;
约束条件已设置。
SQL> INSERT INTO T VALUES (1, 'E');
已创建 1 行。
SQL> SAVEPOINT A;
保存点已创建。
SQL> INSERT INTO T VALUES (1, 'F');
已创建 1 行。
SQL> ROLLBACK TO A;
回退已完成。
SQL> SELECT * FROM T;
ID NAME
---------- ------------------------------
1 A
2 B
3 C
1 E
SQL> INSERT INTO T VALUES (1, 'F');
已创建 1 行。
ROLLBACK TO SAVEPOINT并不会改变延迟约束的状态。而COMMIT和ROLLBACK之所以改变了延迟约束的状态,实际上是COMMIT和ROLLBACK语句使得延迟约束的状态恢复到了默认情况,也就是非延迟状态。











