1 、约束的类型

Table 5-1 Types of Constraints

Constraint Type Description See Also

NOT NULL

Allows or disallows inserts or updates of rows containing a null in a specified column.

"NOT NULL Integrity Constraints"

Unique key

Prohibits multiple rows from having the same value in the same column or combination of columns but allows some values to be null.

"Unique Constraints"

Primary key

Combines a NOT NULL constraint and a unique constraint. It prohibits multiple rows from having the same value in the same column or combination of columns and prohibits values from being null.

"Primary Key Constraints"

Foreign key

Designates a column as the foreign key and establishes a relationship between the foreign key and a primary or unique key, called thereferenced key.

"Foreign Key Constraints"

Check

Requires a database value to obey a specified condition.

"Check Constraints"

REF

Dictates types of data manipulation allowed on values in a REF column and how these actions affect dependent values. In an object-relational database, a built-in data type called aREF encapsulates a reference to a row object of a specified object type. Referential integrity constraints onREF columns ensure that there is a row object for theREF.

Oracle Database Object-Relational Developer's Guide to learn aboutREF constraints


2、NOT NULL:  非空约束

非空约束要求表的一个列没有空值,默认情况下,表的所有行是可以为空的,null的数据类型为字符型,至于说是varchar还是char未知

2.1、非空约束的创建

建表时创建非空约束

SQL> create table rice (id number,

name varchar2(2) not null);

表已创建。

建表后创建非空约束

SQL> create table rice1 (id number,

name varchar2(2) );

表已创建。

SQL> alter table rice1 modify name varchar2(2) not null;

表已更改。

SQL> desc rice1

名称                                                                             是否为空? 类型

------------------------------------------------------------------------------ -------- ----

ID                                                                                    NUMBER

NAME                                                                          NOT NULL VARCHAR2(2)

删除非空约束

SQL> alter table rice1 modify name varchar2(2) null;
表已更改。

SQL> desc rice1
 名称                                                                                                      是否为空? 类型
 ----------------------------------------------------------------------------------------------------------------- -------- -------
 ID                                                                                                                 NUMBER
 NAME                                                                                                               VARCHAR2(2)

有非空约束的表,插入空值

SQL> insert into rice values(1,'');
insert into rice values(1,'')
                          *
第 1 行出现错误:
ORA-01400: 无法将 NULL 插入 ("SCOTT"."RICE"."NAME")


2.3 什么时候创建非空约束
 默认情况下,一个列上是可以包含空值的,为了保证那一列上不在具有空值,可以创建非空约束。
  (1)列必须是非空的情况
   (2)
  • You want to allow index scans of the table, or allow an operation that requires indexing all rows.

    Oracle Database indexes do not store keys whose values are all NULL. Therefore, for the preceding kinds of operations, at least one indexed column must have aNOTNULL constraint.

我对这句话我总是很不理解,你想通过索引扫描整个表,必须添加非空约束

举例:

SQL> create table rice(id number not null , name varchar2(5));

表已创建。

SQL> create table rice1(id number  , name varchar2(5));

表已创建

SQL> desc rice
       名称                                                                                       是否为空? 类型

--------------------------------------------------------------------------------------------------------- -------

ID                                                                                         NOT NULL NUMBE

NAME                                                                                     VARCHAR2(5)

SQL >desc rice1

名称                                                                                                      是否为空? 类型

----------------------------------------------------------------------------------------------------------------- -------- --------

ID                                                                                                       NUMBER

NAME                                                                                              VARCHAR2(5)

SQL>  begin

2   for i in 1..1000 loop

3   insert into rice values(i,'ai');

4   commit;

5   insert into rice1 values(i,'bi');

6   commit;

7   end loop;

8   end;

9   /

PL/SQL 过程已成功完成。

SQL> create index ind_id on rice(id);

索引已创建。

SQL> create index ind_id1 on rice1(id);

索引已创建。

SQL>  select /*+ index(rice ind_id)*/count(*) from rice;

执行计划

----------------------------------------------------------

Plan hash value: 3112229557

-------------------------------------------------------------------

| Id  | Operation        | Name   | Rows  | Cost (%CPU)| Time     |

-------------------------------------------------------------------

|   0 | SELECT STATEMENT |        |     1 |     8   (0)| 00:00:01 ||   1 |

SORT AGGREGATE  |        |     1 |            |          ||   2 |

INDEX FULL SCAN| IND_ID |  1000 |     8   (0)| 00:00:01 |

-------------------------------------------------------------------

SQL>  select /*+ index(rice ind_id1)*/count(*) from rice1;

执行计划

----------------------------------------------------------

Plan hash value: 120591672

--------------------------------------------------------------------

| Id  | Operation          | Name  | Rows  | Cost (%CPU)| Time     |

--------------------------------------------------------------------

|   0 | SELECT STATEMENT   |       |     1 |     3   (0)| 00:00:01 ||   1 |

SORT AGGREGATE    |       |     1 |            |          ||   2 |

TABLE ACCESS FULL| RICE1 |  1000 |     3   (0)| 00:00:01 |

--------------------------------------------------------------------

结论:表rice上有非空约束,要求走索引,走了索引,但是rice2上没有非空约束,要求走索引没有走索引

3、Unique key: 唯一约束

(1)唯一约束要求一列或者组合列上是唯一的,没有重复的,唯一约束适合在任何列或组合列上建,当然这些列或组合列值不能重复。

(2)唯一约束和主键约束是不同的,因为空值永远满足唯一约束,而空值却不满足于主键约束

唯一约束的限制:

  • None of the columns in the unique key can be of LOB, LONG, LONG RAW, VARRAY, NESTED TABLE,OBJECT,REF,TIMESTAMPWITHTIMEZONE, or user-defined type. However, the unique key can contain a column ofTIMESTAMPWITHLOCALTIMEZONE.

  • A composite unique key cannot have more than 32 columns.

  • You cannot designate the same column or combination of columns as both a primary key and a unique key.

  • You cannot specify a unique key when creating a subview in an inheritance hierarchy. The unique key can be specified only for the top-level (root) view.

3.1建立唯一约束

建表时建立唯一约束

      SQL> create table rice(email varchar2(7)

                        constraint e_notnull not null ,

                         constraint e_uk unique(email));

表已创建。

      SQL> insert into rice values('a');
      已创建 1 行。

      SQL> insert into rice values('a');
        insert into rice values('a')
         *
        第 1 行出现错误:
       ORA-00001: 违反唯一约束条件 (SCOTT.E_UK)

建表后建立唯一约束

             SQL> create table rice1(id number,name varchar(2));
            表已创建。

SQL> alter table rice1 add constraint c_idd unique(id);
          表已更改。

删除唯一约束      
             SQL> alter table rice1 drop constraints c_idd;
            表已更改。

  3.2 唯一约束可以插入多个空值

SQL> drop table rice;

表已删除。

SQL> create table rice(id number constraint c_id not null,

name char(5) ,

constraint c_name unique(name));

表已创建。

SQL> insert into rice values(1,'a');

已创建 1 行。

SQL> insert into rice values(1,'');

已创建 1 行。

SQL> insert into rice values(1,'');

已创建 1 行。

SQL> insert into rice values(2,'');

已创建 1 行。

SQL> select *From rice;

ID NAME

---------- -----

1 a

1

1

2

3.3、查看约束:

SQL>  select OWNER,CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME,DEFERRABLE,DEFERRED From dba_constraints WHERE table_name='RICE';

OWNER                     CONSTRAINT_NAME                C TABLE_NAME                     DEFERRABLE     DEFERRED
---------------------------------------------- ------------------------------ - ------------------------------ -------------- ---------
SCOTT                                     C_ID                           C RICE                   NOT DEFERRABLE IMMEDIATE
SCOTT                                  C_NAME                       U RICE                   NOT DEFERRABLE IMMEDIATE

3.4、对比唯一约束和主键约束

SQL> truncate table rice;

SQL> alter table rice add constraints pk_id1 primary key(id1)
  2  ;

SQL>  select OWNER,CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME,DEFERRABLE,DEFERRED From dba_constraints WHERE table_name='RICE';

OWNER                                CONSTRAINT_NAME                C TABLE_NAME                     DEFERRABLE     DEFERRED
--------------------------------- ------------------------------ - ------------------------------ -------------- ---------
SCOTT                                   C_ID                           C RICE                   NOT DEFERRABLE IMMEDIATE
SCOTT                                  PK_ID1                         P RICE                   NOT DEFERRABLE IMMEDIATE
SCOTT                                 C_NAME                         U RICE                   NOT DEFERRABLE IMMEDIATE

主键约束显示为p 唯一约束显示为p

id1 列建主键约束

id列是非空约束

name 是唯一约束

SQL> insert into rice values(1,'a',1);

已创建 1 行。

SQL> select *From rice;

ID NAME         ID1
---------- ----- ----------
         1 a              1

主键约束不能为空

SQL> insert into rice values(1,null,null);
insert into rice values(1,null,null)
                               *
第 1 行出现错误:
ORA-01400: 无法将 NULL 插入 ("SCOTT"."RICE"."ID1")

主键是唯一的,不能重复

SQL> insert into rice values(1,null,1);
insert into rice values(1,null,1)
*
第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (SCOTT.PK_ID1)

唯一约束列可以插入空值
                 SQL> insert into rice values(1,null,2);

已创建 1 行。

唯一约束不能重复(空值比较特殊)

SQL> insert into rice values(1,'a',2);
insert into rice values(1,'a',2)
*
第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (SCOTT.C_NAME)

3.5 唯一索引和唯一约束的区别

(1)创建方法不一样

SQL> create table rice(id number,id1 number);
表已创建。

SQL> create unique index u_id on rice(id);
索引已创建。

SQL> alter table rice add constraint c_id1 unique(id1);
表已更改。

(2)数据库在创建唯一约束时强制创建或者重复使用列上的索引,如果之前的列上没有索引,那么强制创建的索引是唯一索引,如果列上已存在索引,就重用存在的索引,不管此索引是否唯一。

建唯一约束自动创建唯一索引

QL> drop table rice;

表已删除。

QL> create table rice(id number,id1 number);

表已创建。

QL> alter table rice add constraints c_unique  unique (id);

表已更改。

SQL>  select OWNER,CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME,DEFERRABLE,DEFERRED From dba_constraints WHERE table_name='RICE';

OWNER                                  CONSTRAINT_NAME                C TABLE_NAME                     DEFERRABLE     DEFERRED
-------------------------------------- ------------------------------ - ------------------------------ -------------- --------
SCOTT                                    C_UNIQUE                       U RICE                   NOT DEFERRABLE IMMEDIATE
SQL>  select INDEX_NAME,INDEX_TYPE,UNIQUENESS,STATUS From user_indexes where table_name='RICE';

INDEX_NAME                     INDEX_TYPE                  UNIQUENES STATUS
------------------------------ --------------------------- --------- --------
C_UNIQUE                       NORMAL                      UNIQUE    VALID

在列id上建立唯一索引,在列id1上建立普通索引,然后在两个列上个建立唯一约束,查看

SQL> alter table rice drop constraint c_unique;
已更改。

SQL> create unique index id_uniqe on rice(id);
索引已创建。

SQL> create  index id_nouniqe on rice(id1);
索引已创建。

SQL> alter table rice add constraint c_id unique(id);
表已更改。

SQL> alter table rice add constraint c_id1 unique(id1);
表已更改。

SQL>  select INDEX_NAME,INDEX_TYPE,UNIQUENESS,STATUS From user_indexes where table_name='RICE';
INDEX_NAME                     INDEX_TYPE                  UNIQUENES STATUS
------------------------------ --------------------------- --------- --------
ID_NOUNIQE                     NORMAL                      NONUNIQUE VALID
ID_UNIQE                       NORMAL                      UNIQUE    VALID

SQL>  select OWNER,CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME,DEFERRABLE,DEFERRED From dba_constraints WHERE table_name='RICE';

OWNER CONSTRAINT_NAME                C TABLE_NAME                     DEFERRABLE     DEFERRED
----- ------------------------------ - ------------------------------ -------------- ---------
SCOTT C_ID1                          U RICE                           NOT DEFERRABLE IMMEDIATE
SCOTT C_ID                           U RICE                           NOT DEFERRABLE IMMEDIATE

创建唯一约束重用列上以前存在的索引,在删约束的时候,不会自动删除存在的索引,如果是创建索引的时候,自动创建的唯一索引,在删除唯一约束的时候,自动删除唯一索引。

SQL> alter table rice drop constraints c_id;
表已更改。

SQL> alter table rice drop constraints c_id1;
表已更改。

SQL>  select INDEX_NAME,INDEX_TYPE,UNIQUENESS,STATUS From user_indexes where table_name='RICE';

INDEX_NAME                     INDEX_TYPE                  UNIQUENES STATUS
------------------------------ --------------------------- --------- --------
ID_NOUNIQE                     NORMAL                      NONUNIQUE VALID
ID_UNIQE                       NORMAL                      UNIQUE    VALID

结论:1、唯一约束是可以插入多个空值的

2、唯一约束和唯一索引是不一样的


4、Primary key:主键约束

(1)主键唯一确定一行,一个表上只能有一个主键,主键可以确定主键列上是没有重复值,那一列或组合列不是空值。

(2)创建主键约束会隐式创建一个唯一索引和非空约束

(3)如果在创建主键约束前,列上就已经存在索引,那么会重复使用存在的索引,如果不存在索引,那么会在那一列上建立一个唯一索引和约束同名。

在删除主键约束时,如果是在创建主键是自动创建的唯一索引,删除约束时同时删除索引,如果创建主键约束时,重复使用已存在索引,删除约束时,索引仍然存在。

4.1创建主键

建表时创建主键

SQL> create table rice (id number primary key ,name varchar2(5));
表已创建。
SQL> insert into rice values(1,'a');
已创建 1 行。

SQL> insert into rice values(1,'a');
insert into rice values(1,'a')
*
第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (SCOTT.SYS_C0013515)

SQL> insert into rice values('','a');
insert into rice values('','a')
                       *
第 1 行出现错误:
ORA-01400: 无法将 NULL 插入 ("SCOTT"."RICE"."ID")

删除主键

SQL> alter table rice drop constraints SYS_C0013515;
表已更改。

建表后创建主键

方法一:

SQL> alter table rice add constraints pk_id  primary key(id);
       表已更改。

也可以通过

方法二:

SQL> create table rice1(id number,name varchar(10));
       表已创建。

SQL> create unique index pk_id1 on rice1(id);
        索引已创建。

SQL> alter table rice1 add  constraints pk_id1 primary key(id );
       表已更改。

两种方法的却别是: 在表比较大的时候可以通过方法二先创建唯一索引 加上online,这样可以不锁表,减少对表的读写堵塞,不影响业务。

SQL> select si.PROPERTY,ui.index_name
  2  from sys.ind$ si,dba_indexes ui,dba_objects uo
  3  where si.obj#=uo.OBJECT_ID
  4  and ui.index_name=uo.OBJECT_NAME
  5  and ui.table_name in ('RICE','RICE1');

PROPERTY INDEX_NAME
---------- ------------------------------
      4097 PK_ID
         1 PK_ID1

Pk_id 对应的16进制为1001,有1000+1,即索引性质:unique+ The index was created by a constraint,而PK_id1  则为unique索引。

5、Foreign key:外键约束

当两张表有有相同的一列或者多列的时候,可以通过外键来连接两个表的关系,也可以叫做参照完整性约束,一个表的约束列必须参照另一个表相同列中定义的值。

外键可以使依赖另外一张表的某个列或多列,也可以是依赖本张表的某个列

The relational model permits the value of foreign keys to match either the referenced primary or unique key value, or be null

5.1外键的创建

SQL> create table t1 as select *From emp;
表已创建。

SQL> create table t2 as select *From dept;
表已创建。

SQL> select *From t1;
     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 17-12月-80            800                    20
      7499 ALLEN      SALESMAN        7698 20-2月 -81           1600        300         30
      7521 WARD       SALESMAN        7698 22-2月 -81           1250        500         30
      7566 JONES      MANAGER         7839 02-4月 -81           2975                    20
      7654 MARTIN     SALESMAN        7698 28-9月 -81           1250       1400         30
      7698 BLAKE      MANAGER         7839 01-5月 -81           2850                    30
      7782 CLARK      MANAGER         7839 09-6月 -81           2450                    10
      7839 KING       PRESIDENT            17-11月-81           5000                    10
      7844 TURNER     SALESMAN        7698 08-9月 -81           1500          0         30
      7900 JAMES      CLERK           7698 03-12月-81            950                    30
      7902 FORD       ANALYST         7566 03-12月-81           3000                    20
      7934 MILLER     CLERK           7782 23-1月 -82           1300                    10
已选择12行。

SQL> select *From t2;
    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

SQL> alter table t1 add constraint  fk_t2 foreign key(deptno) references t2(deptno);
alter table t1 add constraint  fk_t2 foreign key(deptno) references t2(deptno)
                                                                       *
第 1 行出现错误:
ORA-02270: 此列列表的唯一关键字或主键不匹配

SQL> alter table t2 add constraint pk_t2 primary key(deptno);
表已更改。

SQL> alter table t1 add constraint  fk_t1 foreign key(deptno) references t2(deptno);
表已更改。

SQL> update t1 set deptno=null where deptno=10;
已更新3行。

SQL> select *From t1;

EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 17-12月-80            800                    20
      7499 ALLEN      SALESMAN        7698 20-2月 -81           1600        300         30
      7521 WARD       SALESMAN        7698 22-2月 -81           1250        500         30
      7566 JONES      MANAGER         7839 02-4月 -81           2975                    20
      7654 MARTIN     SALESMAN        7698 28-9月 -81           1250       1400         30
      7698 BLAKE      MANAGER         7839 01-5月 -81           2850                    30
      7782 CLARK      MANAGER         7839 09-6月 -81           2450
      7839 KING       PRESIDENT            17-11月-81           5000
      7844 TURNER     SALESMAN        7698 08-9月 -81           1500          0         30
      7900 JAMES      CLERK           7698 03-12月-81            950                    30
      7902 FORD       ANALYST         7566 03-12月-81           3000                    20
      7934 MILLER     CLERK           7782 23-1月 -82           1300

已选择12行。

结论:(1)外键参考的表上的列必须有主键

(2)外键可以为空

5.2  外键和主表的引用键在删除的时候会有一些矛盾,比如,在删除主表的引用键的行,或者修改主表引用键

DML Statements Allowed by Update and Delete No Action

DML Statement Issued Against Parent Table Issued Against Child Table

INSERT

Always OK if the parent key value is unique

OK only if the foreign key value exists in the parent key or is partially or all null

UPDATE NO ACTION

Allowed if the statement does not leave any rows in the child table without a referenced parent key value

Allowed if the new foreign key value still references a referenced key value

DELETE NO ACTION

Allowed if no rows in the child table reference the parent key value

Always OK

DELETE CASCADE

Always OK

Always OK

DELETE SET NULL

Always OK

Always OK

1)删除主键,外键数据也级联删除

SQL> create table t1 (id number

,name varchar2(10),

constraints pk_id primary key(id));
表已创建。

SQL> create table t2(id number,

course varchar2(5),

constraints fk_id foreign key (id) references t1(id) on delete cascade);

表已创建。

SQL> insert into t1 values(1,'a');

已创建 1 行。

SQL> insert into t1 values(2,'b');

已创建 1 行。

SQL> insert into t1 values(3,'c');

已创建 1 行。

SQL> insert into t2 values(2,'maths');

已创建 1 行。

SQL> insert into t2 values(3,'maths');

已创建 1 行。

SQL> commit;

提交完成。

SQL> select *from t1;

ID NAME
---------- --------------------
         1 a
         2 b
         3 c

SQL> select *from t2;

ID COURSE
---------- ----------
         2 maths
         3 maths

SQL> update t1 set id=null where id=2;
update t1 set id=null where id=2
              *
第 1 行出现错误:
ORA-01407: 无法更新 ("SCOTT"."T1"."ID") 为 NULL

SQL> delete t1 where id=2;

已删除 1 行。

SQL> select *From t1;

ID NAME
---------- --------------------
         1 a
         3 c

SQL> select *From t2;

ID COURSE
---------- ----------
         3 maths

(2)主表删除,外键表设置成空

SQL> create table t1 (id number,

name varchar2(10)  ,

constraints pk_id primary key(id));

表已创建。

SQL> create table t2(id number,

course varchar2(5),

constraints fk_id foreign key (id) references t1(id) on delete set null);

表已创建。

SQL>  insert into t1 values(1,'a');

已创建 1 行。

SQL>  insert into t1 values(2,'b');

已创建 1 行。

SQL>  insert into t1 values(3,'c');

已创建 1 行。

SQL>  insert into t2 values(2,'maths');

已创建 1 行。

SQL>  insert into t2 values(3,'maths');

已创建 1 行。

SQL> commit;

提交完成。

SQL> select *from t1;

ID NAME
---------- --------------------
         1 a
         2 b
         3 c

SQL> select *from t2;

ID COURSE
---------- ----------
         2 maths
         3 maths

SQL> delete t1  where id=2;

已删除 1 行。

SQL> select *from t1;

ID NAME
---------- --------------------
         1 a
         3 c

SQL> select *from t2;

ID COURSE
---------- ----------
           maths
         3 maths

SQL> roll
回退已完成。
SQL> update t1 set id=4 where id=3;
update t1 set id=4 where id=3
*
第 1 行出现错误:
ORA-02292: 违反完整约束条件 (SCOTT.FK_ID) - 已找到子记录

5.3 锁和外键

在大多数情况下,用户需要在外键(foreign key)上创建索引。但有一种情况例外,当外键所引用的主键(primary key)或唯一键(unique key)从不更新或删除时,外键上可以不创建索引。 如果不在外键上建立索引,那么对主键更新时会对外键表瞬时产生一个4号锁,会阻止外键表的dml操作。

如果外键上没有定义索引,对父表的主键执行 DML 操作时必须获得子表上的共享行排他表级锁(share row exclusive table lock)(也称为share-subexclusive table lock,SSX)。此锁能够阻止其他事务对子表执行 DML 操作。SSX 锁在获得后立即释放。如果父表中有多个主键值被更新或删除,对每行执行 DML 操作时都需要对子表进行一次加锁及解锁操作。
 如果外键上定义了索引,则对父表的主键执行 DML 操作时只需获得子表上的行共享表级锁(row share table lock)(也称为 subshare table lockSS)。此锁不允许其他事务排他地对子表加锁,但允许对父表及子表执行 DML 操作。如果对子表进行更新操作的同时有可能存在对父表的更新或删除操作,则适宜采取本节讲述的锁机制。对父表的插入,更新,及删除操作无需获得子表上的锁,但更新及删除操作需要等待子表索引上的行级锁。

如果子表的外键约束定义中指定了 ON DELETE CASCADE 选项,则删除主表数据时将导致相关的子表数据同时被删除。在这种情况下,Oracle 采用的锁机制与用               户先手工地删除子表数据,再删除相关的主表数据时采用的锁机制相同。

6、Check: 检查约束
check约束是建立一列或者一组列上,要求条件为真,才能插入。

建表时创建check约束

SQL> create table t1(id number check(id>1 and id<10),

id1 number check(id1 in (1,2)));

表已创建。

SQL> insert into t1 values(11,1)
  2  ;
insert into t1 values(11,1)
*
第 1 行出现错误:
ORA-02290: 违反检查约束条件 (SCOTT.SYS_C0013556)

SQL> insert into t1 values(10,1)
  2  ;
insert into t1 values(10,1)
*
第 1 行出现错误:
ORA-02290: 违反检查约束条件 (SCOTT.SYS_C0013556)

SQL> insert into t1 values(9,1)
  2  ;

已创建 1 行。

指定约束名:

SQL> create table t2(x varchar2(2),constraints ckeck_x check(x='f'or x='m'));

表已创建。

删除约束:

SQL> alter table t2 drop constraints  ckeck_x;

表已更改。

SQL> insert into t2 values('m');

已创建 1 行。

commit;

建表后创建约束:

SQL> alter table t2 add constraints ckeck_a check(x in ('a','b'));
alter table t2 add constraints ckeck_a check(x in ('a','b'))
                               *
第 1 行出现错误:
ORA-02293: 无法验证 (SCOTT.CKECK_A) - 违反检查约束条件

SQL> select *From t2;

X
--
m

因为表中已经存在数据,再建约束和以前的约束不一样,所以会报错

SQL> alter table t2 add constraints ckeck_a check(x in ('a','b')) novalidate;

表已更改。

SQL> insert into t2 values('y');
insert into t2 values('y')
*
第 1 行出现错误:
ORA-02290: 违反检查约束条件 (SCOTT.CKECK_A)

SQL> insert into t2 values('a');

已创建 1 行。

这时可以加novalidate,使得约束对已存在的数据不检测,只检查新添加进来的数据。

7、REF:

8 约束的状态 

你可以指定一个约束用来约束现有数据或是以后新插入的数据

If you change the state of any single constraint from ENABLE NOVALIDATE to ENABLE VALIDATE, then the operation can be performed in parallel, and does not block reads, writes, or other DDL operations.

你不能让外键引用一个关闭的主键或者唯一键

Modified Data Existing Data Summary

ENABLE

VALIDATE

Existing and future data must obey the constraint. An attempt to apply a new constraint to a populated table results in an error if existing rows violate the constraint.

ENABLE

NOVALIDATE

The database checks the constraint, but it need not be true for all rows. Thus, existing rows can violate the constraint, but new or modified rows must conform to the rules.

DISABLE

VALIDATE

The database disables the constraint, drops its index, and prevents modification of the constrained columns.

DISABLE

NOVALIDATE

The constraint is not checked and is not necessarily true.

If you enable a unique or primary key constraint, and if no index exists on the key, then Oracle Database creates a unique index. Unless you specifyKEEP INDEX when subsequently disabling the constraint, this index is dropped and the database rebuilds the index every time the constraint is reenabled.

如果你打开唯一索引或者主键约束,在那一列上没有索引,那么oracle会创建一个唯一索引。除非你在关闭约束的时候指定keep index。这个索引会随着约束关闭而删除,随着约束的启用而打开

(1)enable+validate  对表中现有数据以及后来的数据都会检测,如果有违反约束的,就会报错。

(2)enable+novalidate 对表中已经存在的数据不检测,对以后的数据insert 或者update会检测

(3)disable+validate 数据库关闭约束,删除约束列上的索引,阻止修改约束列的值,但是约束是合法的,多用在数据仓库中,可以让你节省索引的空间

(4)disable+novalidate 约束不会检测

You cannot drop a table whose primary key is being referenced by a foreign key even if the foreign key constraint is inDISABLENOVALIDATE state. Further, the optimizer can use constraints inDISABLENOVALIDATE state.

SQL> create table t1(id number check(id>1 and id<10),

id1 number check(id1 in (1,2)));

表已创建。

SQL> select constraint_name,constraint_type,STATUS ,VALIDATED,DEFERRABLE from dba_constraints where table_name='T1';

CONSTRAINT_NAME                C STATUS   VALIDATED     DEFERRABLE
------------------------------ - -------- ------------- --------------
SYS_C0013557                   C ENABLED  VALIDATED     NOT DEFERRABLE
SYS_C0013556                   C ENABLED  VALIDATED     NOT DEFERRABLE

SQL> alter table t1 disable constraints SYS_C0013557;

表已更改。

SQL> select *From t1;

ID        ID1
---------- ----------
         9          1

SQL> select constraint_name,constraint_type,STATUS ,VALIDATED,DEFERRABLE from dba_constraints where table_name='T1';

CONSTRAINT_NAME                C STATUS   VALIDATED     DEFERRABLE
------------------------------ - -------- ------------- --------------
SYS_C0013556                   C ENABLED  VALIDATED     NOT DEFERRABLE
SYS_C0013557                   C DISABLED NOT VALIDATED NOT DEFERRABLE

如果你在关闭约束的时候,没有指定约束的状态,关闭约束同时状态也变成not validate

SQL> alter table t1 disable validate constraints SYS_C0013557;

表已更改。

SQL> select constraint_name,constraint_type,STATUS ,VALIDATED,DEFERRABLE from dba_constraints where table_name='T1';

CONSTRAINT_NAME                C STATUS   VALIDATED     DEFERRABLE
------------------------------ - -------- ------------- --------------
SYS_C0013556                   C ENABLED  VALIDATED     NOT DEFERRABLE
SYS_C0013557                   C DISABLED VALIDATED     NOT DEFERRABLE

SQL> update t1 set id1=1 where id=2;
update t1 set id1=1 where id=2
*
第 1 行出现错误:
ORA-25128: 不能对带有禁用和验证约束条件 (SCOTT.SYS_C0013557) 的表进行插入/更新/删除

说明 约束列disable+validate状态不能修改约束列的值

SQL> select INDEX_NAME,STATUS From dba_indexes where table_name='T1';

INDEX_NAME                     STATUS
------------------------------ --------
PK_T1                          VALID

SQL> select constraint_name,constraint_type,STATUS ,VALIDATED,DEFERRABLE from dba_constraints where table_name='T1';

CONSTRAINT_NAME                C STATUS   VALIDATED     DEFERRABLE
------------------------------ - -------- ------------- --------------
PK_T1                          P ENABLED  VALIDATED     NOT DEFERRABLE

SQL> alter table t1 disable constraints pk_t1;

表已更改。

SQL> select INDEX_NAME,STATUS From dba_indexes where table_name='T1';

未选定行

SQL> select constraint_name,constraint_type,STATUS ,VALIDATED,DEFERRABLE from dba_constraints where table_name='T1';

CONSTRAINT_NAME                C STATUS   VALIDATED     DEFERRABLE
------------------------------ - -------- ------------- --------------
PK_T1                          P DISABLED NOT VALIDATED NOT DEFERRABLE

说明:关闭约束会删除索引

SQL> alter table t1 disable constraints pk_t1 keep index;

表已更改。

SQL> select INDEX_NAME,STATUS From dba_indexes where table_name='T1';

INDEX_NAME                     STATUS
------------------------------ --------
PK_T1                          VALID

SQL> select constraint_name,constraint_type,STATUS ,VALIDATED,DEFERRABLE from dba_constraints where table_name='T1';

CONSTRAINT_NAME                C STATUS   VALIDATED     DEFERRABLE
------------------------------ - -------- ------------- --------------
PK_T1                          P DISABLED NOT VALIDATED NOT DEFERRABLE

SQL> insert into t1 select *from emp;
insert into t1 select *from emp
*
第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (SCOTT.PK_EMPNO)

结论:通过keep index 命令可以保留索引,在开启约束的时候可以不用建索引,但是保留索引,索引是唯一索引保证了索引的唯一性

9、延迟约束

每一个约束要么是延迟的,要么是非延迟的,这种状态决定了约束的合法性,

如果是非延迟约束,会在每个语句执行时候检测合法性,如果违反约束则回滚。

如果是延迟约束,可以分为两种,一种是INITIALLY IMMEDIATE 一种是INITIALLY DEFERRED,延迟约束允许用户使用set constraints 使用约束在commited的时候检测约束。延迟约束只是让你暂时关闭约束,进行更改可能违反约束的数据,直到没有违反约束。

你不能更改延迟性约束,除非删除重建。 不能把延迟性约束通过alter 变成no deferred

INITIALLY IMMEDIATE:会在语句执行的时候检测约束

INITIALLY DEFERRED:在语句执行的时候不检测,但是在commite的时候会检测约束,如果违反约束会回退。

建立延迟约束:

SQL> create table tt(id number ,constraints un_id unique(id) initially deferred deferrable);

表已创建。

SQL>  select TABLE_NAME, constraint_name,constraint_type,STATUS ,VALIDATED,DEFERRABLE,DEFERRED from dba_constraints where table_name='TT';
TABLE_NAME CONSTRAINT CO STATUS           VALIDATED                  DEFERRABLE                   DEFERRED
---------- ---------- -- ---------------- -------------------------- ---------------------------- ------------------
TT         UN_ID      U  ENABLED          VALIDATED                  DEFERRABLE                   DEFERRED

SQL> select INDEX_NAME,INDEX_TYPE ,UNIQUENESS from dba_indexes where table_name='TT';

INDEX_NAME                                                   INDEX_TYPE                                     UNIQUENESS
------------------------------------------------------------ ------------------------------------------------------ ----
UN_ID                                                        NORMAL                                         NONUNIQUE

SQL> insert into t1 values(1);
insert into t1 values(1)
            *
第 1 行出现错误:
ORA-00947: 没有足够的值

SQL> insert into tt values(1);

已创建 1 行。

SQL> insert into tt values(1);

已创建 1 行。

SQL> commit;
commit
*
第 1 行出现错误:
ORA-02091: 事务处理已回退
ORA-00001: 违反唯一约束条件 (SCOTT.UN_ID)

SQL> create table tt1(id number ,constraints un_id1 unique(id) initially immediate deferrable);

表已创建。

SQL>  select TABLE_NAME, constraint_name,constraint_type,STATUS ,VALIDATED,DEFERRABLE,DEFERRED from dba_constraints where table_name='TT1';

TABLE_NAME CONSTRAINT CO STATUS           VALIDATED                  DEFERRABLE                   DEFERRED
---------- ---------- -- ---------------- -------------------------- ---------------------------- ------------------
TT1        UN_ID1     U  ENABLED          VALIDATED                  DEFERRABLE                   IMMEDIATE

SQL> select INDEX_NAME,INDEX_TYPE ,UNIQUENESS from dba_indexes where table_name='TT1';

INDEX_NAME                                                   INDEX_TYPE                                     UNIQUENESS
------------------------------------------------------------ ------------------------------------------------------ --------
UN_ID1                                                       NORMAL                                         NONUNIQUE

SQL> insert into tt1 values(1);

已创建 1 行。

SQL> insert into tt1 values(1);
insert into tt1 values(1)
*
第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (SCOTT.UN_ID1)

结论:延迟约束,上的索引都是非唯一索引;

SQL> create table t1(id number not null deferrable);

表已创建。

SQL> create table t2(id number not null );

表已创建。

SQL> create index id_t1 on t1(id);

索引已创建。

SQL> create index id_t2 on t2(id);

索引已创建。

SQL> insert into t1 values(1);

已创建 1 行。

SQL> select *from t1;

ID
----------
         1

SQL> select *from t2;

ID
----------
         1

SQL> set autot trace
SQL> select  count(*) from t2;

执行计划
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=1)
   1    0   SORT (AGGREGATE)
   2    1     INDEX (FAST FULL SCAN) OF 'ID_T2' (INDEX) (Cost=2 Card=1
          )

SQL> select  count(*) from t1;

执行计划
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=3 Card=1)
   1    0   SORT (AGGREGATE)
   2    1     TABLE ACCESS (FULL) OF 'T1' (TABLE) (Cost=3 Card=1)

结论:非空的非延迟约束+索引在select country(*) from t 时会走索引;如果是非空的延迟约束存在+索引是不会走索引的;

遗留问题:(1)外键和锁的试验

(2)关闭主键约束保留唯一索引,仍然可以保证唯一性,但是不能保证空值,那么关闭约束的意义在哪?

constraints相关推荐

  1. R语言构建xgboost模型:指定特征交互方式、单调性约束的特征、获取模型中的最终特征交互形式(interaction and monotonicity constraints)

    R语言构建xgboost模型:指定特征交互方式.单调性约束的特征.获取模型中的最终特征交互形式(interaction and monotonicity constraints) 目录

  2. Advanced Auto Layout:Programmatically Creating Constraints

    Programmatically Creating Constraints以编程方式创建约束 Whenever possible, use Interface Builder to set your ...

  3. 解决eclipse+MAVEN提示One or more constraints have not been satisfied.的问题

    解决eclipse+MAVEN提示One or more constraints have not been satisfied.的问题 参考文章: (1)解决eclipse+MAVEN提示One o ...

  4. SQL高级---SQL 约束 (Constraints)

    SQL 约束 (Constraints) SQL 约束 约束用于限制加入表的数据的类型. 可以在创建表时规定约束(通过 CREATE TABLE 语句),或者在表创建之后也可以(通过 ALTER TA ...

  5. error: goland --build constraints exclude all Go files

    首先,//+build将逐渐取代//go:build,在Go Version1.16-1.18作为过渡期,两种注释都可以使用.参见官网https://www.jetbrains.com/help/go ...

  6. oracle中constraints,oracle constraints(2)

    oracle 约束的状态 oracle在创建约束后默认状态是enabled VALIDATED SQL> create table T2 2 ( 3 VID NUMBER, 4 VNAME VA ...

  7. Unable to simultaneously satisfy constraints.

    开发版本  7.0 @property(nonatomic) BOOL translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0); ...

  8. maven项目,提示One or more constraints have not been satisfied

    环境 JDK 1.8 Eclipse 4.7(javaee) Eclipse Tomcat server plugin Maven 3.5 问题现象 显示错误:One or more constrai ...

  9. SQLite 入门教程(三)好多约束 Constraints

    一.约束 Constraints 在上一篇随笔的结尾,我提到了约束, 但是在那里我把它翻译成了限定符,不太准确,这里先更正一下,应该翻译成约束更贴切一点. 那么什么是约束呢? 我们在数据库中存储数据的 ...

  10. 自动布局报错(两条连线冲突):Unable to simultaneously satisfy constraints

    这个报错有些长: Unable to simultaneously satisfy constraints.     Probably at least one of the constraints ...

最新文章

  1. DateReader,DateAdapter,DateSet和SqlCommand的基本使用方法
  2. 2018.09.01 poj3071Football(概率dp+二进制找规律)
  3. dojo Quick Start/dojo入门手册--json
  4. 每天一道LeetCode-----在有序的二维数组中查找某个元素
  5. iOS学习笔记37 时间和日期计算
  6. 20220211-CTF CRYPTO-base64-凯撒密码-摩丝密码--非常简单的三道题
  7. 前端学习(2965):路由的参数传递
  8. Java 128陷阱+自动装箱拆箱
  9. MAX187_量程0-2.5伏电压表_软件滤波
  10. 2500万美元和AI专家!谷歌出钱出人,要用AI做“对社会有益”的事情
  11. new Date()浏览器兼容性问题
  12. java spring boot 项目 热加载 有利于快速开发
  13. mysql+proxysql+keepalived实现高可用的数据库读写分离
  14. [软件应用]官方下载Nero-9.4.13.2d_update.exe迅雷竟也报毒
  15. 《linux核心应用命令速查》连载五:atq:显示目前使用at命令后待执行的命令队列...
  16. 网页中无法复制的文字如何复制
  17. 使用 CC-359 数据集进行 MRI 重建(二)
  18. 怎么mac ftp服务器文件夹,mac 访问 ftp服务器文件夹权限
  19. 小红书MVP系统架构与技术选型(一)
  20. 1034. 边框着色

热门文章

  1. 怎么做自媒体电影素材下载?怎么快速下载电影素材?
  2. 手把手教你使用vue创建第一个vis.js
  3. 水月雨发布Sparks火花TWS蓝牙耳机:二次元包装,半透明充电盒
  4. ubuntu mysql 优化_在Ubuntu上使用MySQL设置远程数据库优化站点性能
  5. 淘派、树图区块链研究院与芒果智娱达成战略合作,助力数字藏品高质量发展...
  6. statement的概念及常用方法
  7. 阿里的easyexcal包实现表格动态导出
  8. 百度编辑器整合html,怎么把百度编辑器(Ueditor)整合到dedecms中
  9. vue批量引入components组件
  10. 开源数据库HAWQ,架构调研