admin 管理员组

文章数量: 887021

约束

约束是针对列的。在用户添加或修改列数据时,它用来对列数据用出一些限制。例如,非空约束限制了列不能为空。这就是约束。


一、非空约束 NOT NULL  
 我们可以在创建表的同时,创建约束。也可以先创建表,以后在有需要时,添回约束。下面我们先说在创建表的同时,创建约束。
1、建立表时指定约束

 先看一个例子:


gyj@OCM> drop table t2;


Table dropped.


gyj@OCM> create table t2(id number(10) constraint c_id not null, name varchar2(20));


Table created.


上面的命令创建T2表,并在ID列上创建名为C_ID的非空约束。其中,CONSTRAINT c_id的C_ID就是约束的名字。如果我们在创建约束时,也可以不为约束起名字,这样就可以省略CONSTRAINTc_id,那么系统将自动为约束命名:


gyj@OCM> drop table t2;


Table dropped.


gyj@OCM> create table t2(id number(10) not null,name varchar2(20));


Table created.


只需要在列名后添加NOT NULL就可以了。这样很简单,但是ORACLE将自动为此约束起一个非常复杂的名字。
这是在创建表的同时创建约束。有些表是在创建之后,才发现应该为表中的某些列添加约束。


下面我们说一下如何在创建表之后,添加约束。
2、在创建表后添加非空约束
语法形式为:alter table 表名 modify (列名 类型(长度)[DEFAULT 默认值] [非空约束]) ;

这条命令的大部分,我们在前一章已经讲过,它可以更改表中指定列的长度、类型和默认值。当然,它还可以为表添加非空约束。注意,这条命令只能为表添加非空约束。其他类型的约束不使用此命令。


gyj@OCM> drop table t2;


Table dropped.


gyj@OCM> create table t2(id number(10), name varchar2(20));


Table created.


gyj@OCM> alter table t2 modify (id constraint c_id not null);


Table altered.


同样,约束名可以省略,如果省略,系统将自定约束名。


3、删除约束

删除约束非常简单,我们看下面的测试吧,删除上面刚建立的t2_ID_NN约束。


gyj@OCM>  alter table t2 drop constraint c_id;


Table altered.


二、条件检查约束 CHECK  

CHECK非常简单,我们看下面的例子。我想将T2表的ID列值的大小,限制为正整数,也就是说能是0或负数:


gyj@OCM> drop table t2;


Table dropped.


gyj@OCM> create table t2(id number(10) constraint c_id_1 check (id>=1),name varchar2(20));


Table created.


向ID列插入一个0试试:


gyj@OCM> insert into t2(id) values(0);
insert into t2(id) values(0)
*
ERROR at line 1:
ORA-02290: check constraint (GYJ.C_ID_1) violated


像上面这样把约束的创建,直接放在列的后,这种方式创建的约束,被称为列级约束,也简称列约束。除了列级约束,还有表级约束,简称表约束。从隶属关系上来讲,列约束的相关信息,和列存储在一起,因此说列约束是属于列的。而表约束的相关信息,则和表存贮在一起,表约束属于表。从功能上讲,列约束和表约束是一样的。创建方式也非常的相似,下面我们建立一个属于表的CHECK约束:


gyj@OCM> drop table t2;


Table dropped.


gyj@OCM> create table t2(id number(10), name varchar2(20),constraint t2_id_1 check (id>=1) );


Table created.


也就是约束并不跟在列之后定义,而是在在所有列之后,另行定义。这样创建的约束,就是在表级创建约束,也就表约束。但是我们要明白,其实表约束仍是约束表中的列的,它仍是对列发挥作用,只不过像上面t2_id_1约束的信息,被存贮在表层,和表放在一起。

约束中,非空约束必须是列约束。其他类型的约束都即可以是列约束,也可以创建为表约束。不过和列约束相比,表约束有一个列约束所不能提供的功能,就是,一个表约束中可以涉及多列:


gyj@OCM> drop table t2;


Table dropped.


gyj@OCM> create table t2(id number(10), 
  2     age number(3), 
  3     name varchar2(20), 
  4     company varchar2(40),
  5     constraint t2_id_1 check (id>=age ) );


Table created.


此约束的意义是规定ID列必须大于等于AGE列的值。像这样涉及两个列的约束,必须在表级创建。在列级创建的约束,只能针对某一个列。
如果是在创建表后再添加约束,命令如下:

gyj@OCM> drop table t2;


Table dropped.


gyj@OCM> create table t2(id number(10), age number(3), name varchar2(20), company varchar2(40));


Table created.


gyj@OCM> alter table t2 add(constraint t2_id_age_c check (id>age));


Table altered.


和添加非空约束相比,仍然是使用ALTER TABLE命令,但不在是MODIFY,而是ADD。这条命令也可以用来为表新增列除了非空约束外,其他类型的约束必须使用此命令添加。这样添加的约束,都是表级约束。

还有就是,在添加约束时,CHECK约束的条件有可能互相冲突:


gyj@OCM> drop table t2;


Table dropped.


gyj@OCM> create table t2(id number(10), age number(3), name varchar2(20), company varchar2(40));


Table created.


gyj@OCM> alter table t2 add(constraint t2_id_11 check (id>=1 ));


Table altered.


gyj@OCM> alter table t2 add(constraint t2_id_12 check (id<=0 ));


Table altered.


我添加了两个约束,分别是t2_id_11和t2_id_12,两个约束都针对ID列,一个约束规定ID列的值一定要大于等于1,另一约束规定ID定必须小于等于0。现在,除了NULL值,ID列再也插入不进去任何值。


三、唯一约束 UNIQUE 

 唯一约束限制了列的值不能有重复。唯一约束必须依赖索引,在创建唯一约束时,将会同时创建相应的索引。有关索引的内容,我们到后面再讲。下面看一下如何创建唯一约束:


gyj@OCM>  drop table t2;


Table dropped.
gyj@OCM> create table t2(id number(10) constraint c_t2_id unique, age number(3), name varchar2(20));


Table created.


 这是在列级定义约束,约束只针对一列。如果想让ID列和AGE列合起来唯一,而单独的ID列和AGE列可以重复,这就是在表中定义约束了。涉及多列的约束,只能在表级创建。


 gyj@OCM>  drop table t2;


Table dropped.


gyj@OCM>  create table t2(id number(10), 
  2     age number(3), 
  3     name varchar2(20),
  4     constraint t2_id_age_u unique(id,age));


Table created.


在表创建后添加索引命令和添回CHECK差不多,我就不再做测试了。


四、主键 PRIMARY KEY 
 主键约束在效果上,相当于唯一约束+非空约束。也就是,即要求列值不能重复,又要求列值必须非空。
 主键约束的创建方式、注意事项,除了把UNIQUE换为PRIMARY KEY外,都和唯一约束相同,关于他的创建,我们到下面和外键约束一起试。要注意的是,在同一列上,不能即有主键约束,又有唯一约束。


五、外键 FOREIGN KEY
主键约束可以单独发挥作用,它的作用相当于唯一+非空。而外键约束则必须主键结合在一起使用。在创建创建约束时,先必须先有一个主键,然后,根据此主键,创建一个相关联的外键约束。也就是说,外键约束必须对应一个主键,不能创建独立的外键约束。
主、外键约束通常创建在不同的表上,通过主、外键关系,可以将不同的表关联起来。外键约束的创建方式、注意事项,和主键约束、唯一约束相同。下面我们通过一个例子,来了解一下他的创建方式和作用:

我建立如下两个表:


gyj@OCM> create table emp1(id number(10), name varchar2(20), dept_id number(10));


Table created.


gyj@OCM> create table dept1(dept_id number(10), dept_name varchar2(20));


Table created.


emp1表是雇员表,包含雇员ID(ID)、姓名(NAME)和部门编号(DEPT)三列。
dept1表是部门表,包括部门编号(DEPT)、部门名称(DEPT_NAME)两列。
这两个表有对应的关系,雇员表的部门编号(DEPT)列,和部门表的部门编号(DEPT)列就是对应的。通常我们可以用这个列作等值连接,将两个表连接在一起显示更详细的信息。现在,需要对这两个表中的相关部门的列作出一些限制。比如,部门表中有A、B、C三个部门,哪么,雇员表中雇员的部门,也只能有A、B、C。也就是部门表中有什么部门,雇员才能是什么部门。不能雇员是D部门,但在部门表中根本就没有此部门。

像这样的限制,我们就可以通过主、外键约束来实现。dept1(部门表)表中的dept_id(部门编号)列应该被设为主键。而雇员表emp11中的dept_id列为外键:


gyj@OCM> alter table dept1 add(constraint c_dept1_p primary key(dept_id));


Table altered.


gyj@OCM> alter table emp1 add(constraint c_emp1_dept1_f foreign key(dept_id) references dept1(dept_id));


Table altered.


注意添加外键约束的命令,foreign key(dept_id)说明要在本表上dept_id列上创建外键约束,references dept1(dept_id)说明此约束关联于DEPT1表中的DEPT_ID列上的主键。在执行此命令前,DEPT1表的DEPT_ID列必须有主键约束或唯一约束。注意,外键约束也可以关联到唯一约束。

现在,向部门表插入三个部门。


gyj@OCM> insert into dept1 values(1,'IT');


1 row created.


gyj@OCM> insert into dept1 values(2,'Administration');


1 row created.


gyj@OCM> insert into dept1 values(3,'Sales');


1 row created.


gyj@OCM> commit;


Commit complete.


如果向EMP1中插入这三个部门的雇员,是没有问题的:


gyj@OCM> insert into emp1 values(1,'Joe',3);


1 row created.


如上,我插入了一个雇员编号为1,姓名为“Joe”的雇员,他属于销售部。但如果我插入部门编号为5的行,插入将会失败:


gyj@OCM>  insert into emp1 values(2,'Rose',5);
 insert into emp1 values(2,'Rose',5)
*
ERROR at line 1:

ORA-02291: integrity constraint (GYJ.C_EMP1_DEPT1_F) violated - parent key not found


主键可以有外键没有的值,但外键不能有主键没有的值。这就是主、外键约束的根据意义。另外,我们通常将主键所在表称为父表,外键所在表称为子表。

此时,以已有一条部门编号为3的雇员,再在主键中删除部门编号为3的行,会出现什么情况呢:


gyj@OCM> delete dept1 where dept_id=3;
delete dept1 where dept_id=3
*
ERROR at line 1:
ORA-02292: integrity constraint (GYJ.C_EMP1_DEPT1_F) violated - child record found


  ORACLE不允许你这么做。你必须先到子表中,删除所有部门编号为3的行,这样才能删除父表中部门编号为3的行。ORACLE可以自动为你做这个工作,但你要把子表的外键,设为级联删除,命令如下:


gyj@OCM> alter table emp1 drop constraint c_emp1_dept1_f;


Table altered.


我先使用上面的命令将原来的外键约束删除。然后再用下面的命令添加可以级联删除的外键约束。


gyj@OCM> alter table emp1 add(constraint c_emp1_dept1_f 
  2     foreign key(dept_id) 
  3     references dept1(dept_id) 
  4     on delete cascade);


Table altered.


on delete cascade表示的就是级联删除行。级联删除的意思,也就是删除主表的部门编号为3的行时,子表中所有部门为3的行都跟着删除。


gyj@OCM> delete dept1 where dept_id=3;


1 row deleted.


gyj@OCM> select * from emp1;


no rows selected


不过,有一点需要注意,这里的级联,并不是针对所有的DML命令,只能针对删除。on delete cascade中有一个DELETE单词,这就说明了这只是“级联删除”。不能级联更新、插入等等。

但更新命令是不可级联的:


gyj@OCM> insert into emp1 values(1,'Jack',2);


1 row created.


gyj@OCM> update dept1 set dept_id=4 where dept_id=2;
update dept1 set dept_id=4 where dept_id=2
*
ERROR at line 1:
ORA-02292: integrity constraint (GYJ.C_EMP1_DEPT1_F) violated - child record found


外键必须对应主键,也就是子表必能对应一个父表。如果父表被删除了,子表怎么办,看试验:


gyj@OCM> drop table dept1;
drop table dept1
           *
ERROR at line 1:
ORA-02449: unique/primary keys in table referenced by foreign keys


ORACLE不允许删除父表。除非使用级联约束:


gyj@OCM>  drop table dept1 cascade constraints
  2  /


Table dropped.


cascade constraints(级联约束)将先删除子表上的外键,再删除父表。cascade constraints在所有涉及约束的命令中都可以使用。比如,我们前面已经讲过的删除列,这可以使用这个选项,在删除列的同时,删除约束。




**********本博客所有内容均为原创,如有转载请注明作者和出处!!!**********
Name:    guoyJoe

QQ:        252803295

Email:    oracledba_cn@hotmail.com

Blog:      

ITPUB:   .html

OCM:     .HTM
 _____________________________________________________________
加群验证问题:哪些SGA结构是必需的,哪些是可选的?否则拒绝申请!!!

答案在:

Oracle@Paradise  总群:127149411

Oracle@Paradise No.1群:177089463(已满)

Oracle@Paradise No.2群:121341761

Oracle@Paradise No.3群:140856036


本文标签: 约束