1. 两种验证时机.

Oracle的constraints(约束) 根据验证时机可以分成两种.

case 1.  在每一句insert statement 执行时就会马上验证, 如果约束验证失败,  则这句sql statement 会执行失败.

case 2.   执行insert statements 时不会验证,   在commit的时候验证, 如果验证失败, 则整个Transaction 回滚.


2.constraints的分类

对应地,  oracle 的 constraints 也可以分成两大类.

一种是not deferrable (不可以延时的) . 这种情况下只能执行 case1 的验证时机(即时验证)

另一种是 defferable (可以设置成延时的).   这种情况下可以执行 case 1 或 case2 的验证时机. 但需要设置.

对于第二种defferable 分类, 还可以分成两小类.

一种是 initially immediate ,  意思时默认情况下执行case 1.

另一种是initially deferred,  意思是默认情况下执行case2.

也就是可以分成三种

1. not deferrable

2. deferrable   initially immediate

3. deferrable   initially deferred.

如下图:

下面会举一些例子来详细解释这个3种 constraints的区别:

2.1 not deferrable constraints

这种最常见也最简单.  如果在增加1个constraint 时不指定验证时机属性. 默认情况下就会被设为not deferrable.

既然constraint 是不可以延时验证的,  所以也不用设定它的初始属性(实际上就是initially immediate)

例子:

首先我们建立1张空表:

create table T1 (id number(10,0),nm varchar(10));

接下来为id列 增加1个唯一约束t1_id:

SQL> alter table T1 add constraint t1_id  unique(id);Table altered.

注意这时并没有指定 Deferrable 属性, 所以默认情况下就是 not deferrable 的. 我们可以通过user_constraints视图来检查它的属性:

SQL> select table_name, constraint_name, status, deferrable, deferred, validated from user_constraints where table_name = 'T1';TABLE_NAME CONSTRAINT_NAME STATUS   DEFERRABLE     DEFERRED  VALIDATED
---------- --------------- -------- -------------- --------- -------------
T1     T1_ID       ENABLED  NOT DEFERRABLE IMMEDIATE VALIDATED

注意Deferrable 属性是 not deferrable.   而 Deferred 属性(Initially 初始属性) 是immediate.

这时我们连续执行3句insert sql:

SQL> insert into T1 values(1, 'abc1');1 row created.SQL> insert into T1 values(2, 'abc2');1 row created.SQL> insert into T1 values(2, 'abc3');
insert into T1 values(2, 'abc3')
*
ERROR at line 1:
ORA-00001: unique constraint (BILL.T1_ID) violated

可以见到第一第二句insert statement 能正常执行,  但第三句执行失败, 因为id=2 与第二句重复了, 约束验证失败.

所以说验证时机属于case1, 即时验证.

这种验证时机也是最常见的.

2.2 deferrable initially immediate constraints

这种约束默认情况下等于第一种约束(not deferrable), 但是它可以在事务中改变设置, 变成延时验证的约束.

我们可以这样理解.

第一个属性deferrable 表示 这个约束可以被设置成延时验证.

第二个属性initially immediate 表示这个约束默认情况下是即时验证.

我们继续利用上面的例子.

首先, 清空上面那个例子表.  由于上面操作没有提交, 所以回滚就ok了.

SQL> rollback;Rollback complete.

然后我们修改(删除再建立)那个约束, 射程deferrable initiallly immediate 模式.

SQL> alter table T1 drop constraint t1_id;Table altered.SQL> alter table T1 add constraint t1_id unique(id) initially immediate deferrable ;Table altered.SQL>

这时我们去user_constraints视图检查属性:

SQL> select table_name, constraint_name, status, deferrable, deferred, validated from user_constraints where table_name = 'T1';TABLE_NAME CONSTRAINT_NAME STATUS   DEFERRABLE     DEFERRED  VALIDATED
---------- --------------- -------- -------------- --------- -------------
T1     T1_ID       ENABLED  DEFERRABLE     IMMEDIATE VALIDATED

可以见到只有1个属性与Not Defferable constraint有区别,  就是 deferrable  属性是 deferrable了.   但是 deferred (初始属性) 还是 immediate.

我们继续尝试插入上面的三行数据:

SQL> insert into T1 values(1, 'abc1');1 row created.SQL> insert into T1 values(2, 'abc2');1 row created.SQL> insert into T1 values(2, 'abc3');
insert into T1 values(2, 'abc3')
*
ERROR at line 1:
ORA-00001: unique constraint (BILL.T1_ID) violated

可以到执行结果与上面一模一样. 没有区别. 也就是说也是case 1模式.

我们检索这张表, 只有两行数据, 然后回滚, 那么就清空这张表了.

SQL> select * from T1;ID NM
---------- ----------1 abc12 abc2SQL> rollback;Rollback complete.SQL> select * from T1;no rows selectedSQL>

好了, 现在就是重点了, deferrable可以在事务中临时改变成另1种模式.

也就是说可以由case1 临时设置为 case 2.

syntax:

set constraint  <constraint_name>  deferred/immediate

注意上面的语句并没有改变这个constraint的任何属性, 只不过是切换为另一种模式

也就是说初始是immediate模式的,   执行上面的语句后就临时变成deferred模式了.

我们接回上面的例子, 执行另一只模式:

SQL> set constraint t1_id deferred;Constraint set.

我们查下这个constraint的属性, 发现属性完全无改变,  Deferred属性还是immediate.  因为Deferred这个属性指的是初始属性.

SQL> select table_name, constraint_name, status, deferrable, deferred, validated from user_constraints where table_name = 'T1';TABLE_NAME CONSTRAINT_NAME STATUS   DEFERRABLE     DEFERRED  VALIDATED
---------- --------------- -------- -------------- --------- -------------
T1     T1_ID       ENABLED  DEFERRABLE     IMMEDIATE VALIDATED

这时我们insert上面的三条记录.  发现3条insert都可以被插入到数据表中.

SQL> insert into T1 values(1, 'abc1');1 row created.SQL> insert into T1 values(2, 'abc2');1 row created.SQL> insert into T1 values(2, 'abc3');1 row created.SQL> select * from T1;ID NM
---------- ----------1 abc12 abc22 abc3SQL>

则说明这时在insert 语句执行时不会执行这个约束的验证, 三行都被插入到表中了,  但是在提交时回验证.

SQL> commit;
commit
*
ERROR at line 1:
ORA-02091: transaction rolled back
ORA-00001: unique constraint (BILL.T1_ID) violated

见到提交失败, 而且整个事务会回滚,  也就是说这时表里面连第一第二句的insert记录也没有了.

SQL> select * from T1;no rows selected

这个跟not defferable constraint有区别啊,  那种在每一句sql statement执行验证, 而且验证失败时并不会回滚事务.

好了下面也是重点:

当我们commit失败后被回滚,  也就是代表当前的事务结束了. 

而上面我们提到过, 使用 set constraint 语句 切换constraint到另一种模式只会在当前事务中生效.

也就是指, 事务结束后, 这个constraint就会返回初始模式!

我们再尝试插入三条语句:

SQL> insert into T1 values(1, 'abc1');1 row created.SQL> insert into T1 values(2, 'abc2');1 row created.SQL> insert into T1 values(2, 'abc3');
insert into T1 values(2, 'abc3')
*
ERROR at line 1:
ORA-00001: unique constraint (BILL.T1_ID) violated

发现再次在第三句执行时被执行即时验证, 因为在新事务中,  constraint t1_id又切换回 immediate 模式了.

2.3 deferrable initially deferred constraints

如果理解了第二种constraint, 那么最后一种就很简单了

第一个属性deferrable 表示 这个约束可以被设置成延时验证.

第二个属性initially immediate 表示这个约束默认情况下是延时验证.

但是可以用set constraint语句 在1个事务中临时切换为 即时验证.

oracle Deferrable constraint 详解以及用法.相关推荐

  1. oracle中to_date详解

    oracle中to_date详解 TO_DATE格式(以时间:2007-11-02 13:45:25为例) 1. 日期和字符转换函数用法(to_date,to_char) 代码如下: select t ...

  2. Oracle 表分区详解(partition table)

    文章目录 1 概述 1.1 思维导图 2 分类 2.1 传统表分区 2.1.1 范围分区 range 2.1.2 列表分区 list 2.1.3 哈希分区 hash 2.1.4 复合分区 range ...

  3. oracle控制文件都一样么,Oracle控制文件详解

    一.Oracle控制文件 为二进制文件,初始化大小由CREATEDATABASE指定,可以使用RMAN备份 记录了当前数据库的结构信息,同时也包含数据文件及日志文件的信息以及相关的状态,归档信息等等 ...

  4. Oracle cursor_sharing 参数 详解

    一. 官网的说明 http://download.oracle.com/docs/cd/E11882_01/server.112/e17110/initparams042.htm#REFRN10025 ...

  5. OpenCV Mat类详解和用法(官网原文)

    参考文章:OpenCV Mat类详解和用法 我马克一下,日后更 官网原文链接:https://docs.opencv.org/3.2.0/d6/d6d/tutorial_mat_the_basic_i ...

  6. oracle参数文件initorcl位置,oracle 参数文件详解

    参数文件 两类参数文件: pfile:文本文件的参数文件,可以使用vi,vim等编辑器修改,文件名通常为init.ora spfile:二进制的参数文件,不能直接修改,只能存放在Oracle服务器端, ...

  7. Oracle建立全文索引详解

    Oracle建立全文索引详解 1.全文检索和普通检索的区别 不使用Oracle text功能,当然也有很多方法可以在Oracle数据库中搜索文本,比如INSTR函数和LIKE操作: SELECT *F ...

  8. oracle做子查询注意事项,Oracle子查询详解

    Oracle子查询详解,根据查询的结果(内部嵌套查询的结果)把子查询的类型分为单行子查询与多行子查询, 子查询概念 :当一个查询的结果是另一个查询的条件时,,称之为子查询. 使用子查询注意事项: 子查 ...

  9. Oracle中CONCAT详解

    Oracle中CONCAT详解 1.什么是CONCAT 新的改变 我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写 ...

最新文章

  1. php内外边距,选择器与内外边距使用方法(margin,padding使用)-2019年9月4日
  2. python 计算文件的MD5
  3. c语言邻接表的构建_c语言数据结构--图的邻接矩阵和邻接表操作的基本操作
  4. 使用Newtonsoft.Json.dll(JSON.NET)动态解析JSON、.net 的json的序列化与反序列化(一)...
  5. java递归深度克隆_递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝。...
  6. ui uview 安卓开发_uni-app UI框架之uview-ui使用教程
  7. php_mongo模块,PHP安装mongo模块详细步骤
  8. 使用R语言进行时间序列分析
  9. 概率假设密度滤波 matlab,概率假设密度滤波的物理空间意义
  10. 无人驾驶到底怎么赚钱?很现实,八仙过海,各显神通
  11. 基于python+django框架+Mysql数据库的校园运动场地预约系设计与实现
  12. P1972 [SDOI2009]HH的项链 区间查询
  13. 完美解决浏览器主页被hao123劫持,打开浏览器时自动进入hao123主页怎么办
  14. 如何将一串数字用函数的方法倒过来(C语言)
  15. 自再现模形成过程matlab,激光原理课程设计--平行平面腔自再现模Fox-Li数值迭代解法及MATLAB实现.doc...
  16. windows下查看端口占用并终止进程
  17. Win7的64位系统安装Apploc
  18. 格式化后数据恢复软件哪个好用?
  19. 一起做一款自己的英语学习助手吧(小程序)
  20. kerberos使用详解

热门文章

  1. html5之form表单
  2. django_rest_framework之GenericAPIView(三)
  3. [ATF]-MTK:一篇文章了解ATF原理
  4. [register]-04-ARMv8的寄存器简介和总结
  5. 一次代码审计实战案例【思路流程】
  6. 【安全技术】红队之windows信息收集思路
  7. 常见的安全应用识别技术有哪些?
  8. Codeforces Round #481 (Div. 3)【完结】
  9. 散列(hash)练习题
  10. python中的encode()和decode()函数