像这样的限制,我们就可以通过主、外键约束来实现。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.
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在所有涉及约束的命令中都可以使用。比如,我们前面已经讲过的删除列,这可以使用这个选项,在删除列的同时,删除约束。
四、利用子查询创建表简称CTAS
gyj@OCM> CREATE TABLE dept80
2 AS SELECT employee_id, last_name,
3 salary*12 ANNSAL,
4 hire_date FROM hr.employees WHERE department_id = 80;
Table created.