[每日一题]OCP1z0-047 :2013-08-03约束―――延迟约束
[每日一题]OCP1z0-047 :2013-08-03约束―――延迟约束
这题是考延迟约束的相关知识点。在表CUST设了主键cust_id(唯一并且非空),在主键设延迟约束,所谓延迟约束就是在dml时数据库不判断数据是否满足约束,在commit时来判断,如果commit,做dml操作时(这道题是插入的数据如果不满足约束条件那就会做rollback)
这道题中,第一行,第二行数据的cust_id都为1,重复了,在提交时肯定会报错,结果会回滚。相当于第一行,第二行不会插入到表CUST中。
第三行,第四行的cust_id分别为1和2,没有重复,提交时插入成功,会永久保存。
所以可以看出正确答案是:C
延迟或立即约束
立即约束就是在每个DML语句执行时,立即判断用户所作的修改是否违返了约束,如果违返了,立即回当前正在执行的DML语句。我们以前我遇到的约束,都是这样的立即约束。
延迟约束在DML语句结束时,并不判断是否违反约束,而是事务提交时再判断。如果约束违反,整个事务被回退。
在创建约束时,有两个选项可以设置约束的检查方式:
Initiallyimmediate :最初为立即约束。
Initially deferred :最初为延迟约束。
如果将约束定为Initiallyimmediate,那么约束仍是立即的,但我们可以使用命令设为延迟的。而约束如果被设为了Initially deferred,约束建立好了,就是延迟的。
我们来试下:
[html] gyj@OCM> drop table t8; Table dropped. gyj@OCM> create table t8(id number(10) constraint t8_id_c check(id>=5) 2 initially deferred,namevarchar2(20)); gyj@OCM> insert into t8 values(1,'gyj'); 1 row created.
可以正常插入。约束的检查被推迟了
gyj@OCM> commit; commit * ERROR at line 1: ORA-02091: transaction rolled back ORA-02290: check constraint (GYJ.T8_ID_C)violated
可以看到,提交时检查出来此事务违反了约束,整个事务被回滚,事务也结束了。注意立即约束中,只会回滚违反约束的当前语句,而不会回滚整个事务。
如果我把约束建立成Initiallyimmediate,最初为立即。那么约束此时还是立即。需要使用如下命令,才能把约束设置为延迟的。而且,最初为延迟的约束,也可以使用此命令,设成立即的。Initiallyimmediate和Initially deferred都是可延迟的约束,下面的这条命令,可以将可延迟的约束,设置为延迟或立即。命令语法如下:
set constraints 约束名|all Immediate|Deferred
比如我上面创建的,是最初为延迟,我们也验证过了,现在已经是延迟检查了,下面我把它改为立即的
gyj@OCM> set constraint t8_id_cimmediate; Constraint set.
t8_id_c已经被改为立即的了,再插入违反约束的行,马上就会报出错误:
gyj@OCM> insert into t8values(1,'gyj'); insert into t8 values(1,'gyj') * ERROR at line 1: ORA-02290: check constraint(GYJ.T8_ID_C)violated
这个命令只影响当前会话,并且只在COMMIT和ROLLBACK命令执行前有效。下面我来试一下,仍旧是在刚才的会话中,执行一个COMMIT或ROLLBACK:
gyj@OCM> rollback; Rollback complete.
执行COMMIT或ROLLBACK那个命令都行,这两个命令都代表一个事务的结束,SET CONSTRAIN命令的作用,也就是维持到一个事务的结束。现在t8_id_c约束又回到了最初的状态,它最初是延迟检查约束。下面我再插入一个违反约束的行:
gyj@OCM> insert into t8 values(1,'gyj'); 1 row created.
已经可以插入了,直到提交才报错:
gyj@OCM> commit; commit * ERROR at line 1: ORA-02091: transaction rolled back ORA-02290: check constraint(GYJ.T8_ID_C)violated
Initiallyimmediate我就不再试验了,除了它最初是立即外,它和Initially deferred的控制操作是一样的。如果在创建约束时,没有加这两个选项中的任一个,约束就是不可延迟的,对于不可延迟的约束,使用SET CONSTRAINT命令会报出错误。
我先把t8表上的约束创建为不可延迟的:
gyj@OCM> drop table t8; Table dropped. gyj@OCM> create table t8(idnumber(10)constraint t8_id_c check (id>=5),name varchar2(20)); Table created.
现在我把t8_id_c约束设为可延迟:
gyj@OCM> set constraint t8_id_cdeferred; setconstraint t8_id_c deferred * ERROR at line 1: ORA-02447: cannot defer a constraintthatis not deferrable
报出了错误,因为AA3_ID_C是不可延迟约束。
SETCONSTRAINT命令的作用,只对当前会话的当前事务有效,另有一条命令,它的作用可以对当前会话中的所有事务有效:
Alter session setconstraint=immediate|Deferred|Default;
immediate是立即,Deferred是延迟,Default是恢复创建约束时所设置的值.
操作如下:
[html] gyj@OCM> drop table t8; Table dropped. gyj@OCM> create table t8(id number(10)constraint t8_id_c check (id>=5),name varchar2(20)); Table created. gyj@OCM> Alter session set constraint=deferred; Session altered.