Oracle開發 之 主-外鍵約束FK及約束的修改


試驗環境:

1)數據庫版本:oracle 11.2.0.4

2)建表腳本:以scott的dept及emp表為基礎。

父表:dept

-- Create table

create table DEPT

(

DEPTNO NUMBER(2) not null,

DNAME VARCHAR2(14),

LOC VARCHAR2(13)

)

-- Create/Recreate primary, unique and foreign key constraints

alter table DEPT

add constraint PK_DEPT primary key (DEPTNO)

using index;

子表emp:

-- Create table

create table EMP

(

EMPNO NUMBER(4) not null,

ENAME VARCHAR2(10),

JOB VARCHAR2(9),

MGR NUMBER(4),

HIREDATE DATE,

SAL NUMBER(7,2),

COMM NUMBER(7,2),

DEPTNO NUMBER(2)

)

-- Create/Recreate primary, unique and foreign key constraints

alter table EMP

add constraint PK_EMP primary key (EMPNO)

using index ;

alter table EMP

add constraint FK_DEPTNO foreign key (DEPTNO)

references DEPT (DEPTNO);

一、主-外鍵約束FK

主-外鍵約束指的是子表的某一字段的內容取值范圍必須由主表指定。

1)創建2張測試表:

create table f1 as select * from dept;

create table s1 as select * from emp;

說明:目前僅僅是復制了表結構及數據,未建立任何約束。

2)在未給f1.deptno創建主鍵或唯一約束,首選為s1.deptno創建外鍵:

SQL> alter table S1 add constraint FK_DEPTNO_S1 foreign key (DEPTNO) references F1 (DEPTNO);

alter table S1 add constraint FK_DEPTNO_S1 foreign key (DEPTNO) references F1 (DEPTNO)

*

ERROR at line 1:

ORA-02270: no matching unique or primary key for this column-list

結論:在子表中設置的與父表關聯的外鍵字段時,這個字段在父表中必須具有主鍵約束或唯一約束才可以設置成功。否則無法設置外鍵約束。

3)首先為F1.DEPTNO創建主鍵約束,然后再在S1.DEPTNO設置依賴於F1的外鍵,即可創建成功。

SQL> alter table F1 add constraint PK_F1 primary key (DEPTNO);

Table altered.

SQL> alter table S1 add constraint FK_DEPTNO_S1 foreign key (DEPTNO) references F1 (DEPTNO);

Table altered.

4)刪除F1的約束pk_f1:

SQL> alter table f1 drop constraint pk_f1;

alter table f1 drop constraint pk_f1

*

ERROR at line 1:

ORA-02273: this unique/primary key is referenced by some foreign keys

結論:若想刪除被外鍵依賴的主鍵信息時,需要首先刪除與其關聯的外鍵,然后再刪除主鍵:

SQL> alter table s1 drop constraint fk_deptno_s1;

Table altered.

SQL> alter table f1 drop constraint pk_f1;

Table altered.

5)首先為F1.DEPTNO創建唯一約束,然后再在S1.DEPTNO設置依賴於F1的外鍵,即可創建成功。

SQL> alter table F1 add constraint UK_F1 unique(deptno);

Table altered.

SQL> alter table S1 add constraint FK_DEPTNO_S1 foreign key (DEPTNO) references F1 (DEPTNO);

Table altered.

6)與步驟4相同:

SQL> alter table f1 drop constraint uk_f1;

alter table f1 drop constraint uk_f1

*

ERROR at line 1:

ORA-02273: this unique/primary key is referenced by some foreign keys

7)總結:外鍵依賴於父表字段的主鍵約束或唯一約束,有外鍵約束時,如果想刪除主鍵或唯一約束需要先刪除其外鍵約束。

8)針對於父表的delete或drop操作,如存在依賴關系需要首先處理子表數據,然后再處理父表數據。

9)針對於對父表的delete操作,外鍵設置on delete cascade:

create table f1 as select * from dept;

create table s1 as select * from emp;

alter table F1 add constraint PK_F1 primary key (DEPTNO)

alter table S1 add constraint FK_DEPTNO_S1 foreign key (DEPTNO) references F1 (DEPTNO) on delete cascade;

查詢現在F1和S1表的數據:

SQL> select * from f1;

DEPTNO DNAME LOC

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

10 ACCOUNTING NEW YORK

20 RESEARCH DALLAS

30 SALES CHICAGO

40 OPERATIONS BOSTON

SQL> select * from s1;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

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

7369 SMITH CLERK 7902 1980/12/17 00:00:00 800 20

7499 ALLEN SALESMAN 7698 1981/02/20 00:00:00 1600 300 30

7521 WARD SALESMAN 7698 1981/02/22 00:00:00 1250 500 30

7566 JONES MANAGER 7839 1981/04/02 00:00:00 2975 20

7654 MARTIN SALESMAN 7698 1981/09/28 00:00:00 1250 1400 30

7698 BLAKE MANAGER 7839 1981/05/01 00:00:00 2850 30

7782 CLARK MANAGER 7839 1981/06/09 00:00:00 2450 10

7788 SCOTT ANALYST 7566 1987/04/19 00:00:00 3000 20

7839 KING PRESIDENT 1981/11/17 00:00:00 5000 10

7844 TURNER SALESMAN 7698 1981/09/08 00:00:00 1500 0 30

7876 ADAMS CLERK 7788 1987/05/23 00:00:00 1100 20

7900 JAMES CLERK 7698 1981/12/03 00:00:00 950 30

7902 FORD ANALYST 7566 1981/12/03 00:00:00 3000 20

7934 MILLER CLERK 7782 1982/01/23 00:00:00 1300 10

14 rows selected.

刪除F1表中10部門數據:

SQL> delete from f1 where deptno=10;

1 row deleted.

SQL> select * from f1;

DEPTNO DNAME LOC

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

20 RESEARCH DALLAS

30 SALES CHICAGO

40 OPERATIONS BOSTON

SQL> select * from s1;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

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

7369 SMITH CLERK 7902 1980/12/17 00:00:00 800 20

7499 ALLEN SALESMAN 7698 1981/02/20 00:00:00 1600 300 30

7521 WARD SALESMAN 7698 1981/02/22 00:00:00 1250 500 30

7566 JONES MANAGER 7839 1981/04/02 00:00:00 2975 20

7654 MARTIN SALESMAN 7698 1981/09/28 00:00:00 1250 1400 30

7698 BLAKE MANAGER 7839 1981/05/01 00:00:00 2850 30

7788 SCOTT ANALYST 7566 1987/04/19 00:00:00 3000 20

7844 TURNER SALESMAN 7698 1981/09/08 00:00:00 1500 0 30

7876 ADAMS CLERK 7788 1987/05/23 00:00:00 1100 20

7900 JAMES CLERK 7698 1981/12/03 00:00:00 950 30

7902 FORD ANALYST 7566 1981/12/03 00:00:00 3000 20

11 rows selected.

SQL> commit;

Commit complete.

結論:在外鍵中使用on delete cascade時,刪除父表的數據時會同時刪除與父表數據相關聯的子表數據。

10)針對於對父表的delete操作,外鍵設置on delete set null:

create table f1 as select * from dept;

create table s1 as select * from emp;

alter table F1 add constraint PK_F1 primary key (DEPTNO);

alter table S1 add constraint FK_DEPTNO_S1 foreign key (DEPTNO) references F1 (DEPTNO) on delete set null;

查詢F1和S1現在數據:

SQL> select * from f1;

DEPTNO DNAME LOC

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

10 ACCOUNTING NEW YORK

20 RESEARCH DALLAS

30 SALES CHICAGO

40 OPERATIONS BOSTON

SQL> select * from s1;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

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

7369 SMITH CLERK 7902 1980/12/17 00:00:00 800 20

7499 ALLEN SALESMAN 7698 1981/02/20 00:00:00 1600 300 30

7521 WARD SALESMAN 7698 1981/02/22 00:00:00 1250 500 30

7566 JONES MANAGER 7839 1981/04/02 00:00:00 2975 20

7654 MARTIN SALESMAN 7698 1981/09/28 00:00:00 1250 1400 30

7698 BLAKE MANAGER 7839 1981/05/01 00:00:00 2850 30

7782 CLARK MANAGER 7839 1981/06/09 00:00:00 2450 10

7788 SCOTT ANALYST 7566 1987/04/19 00:00:00 3000 20

7839 KING PRESIDENT 1981/11/17 00:00:00 5000 10

7844 TURNER SALESMAN 7698 1981/09/08 00:00:00 1500 0 30

7876 ADAMS CLERK 7788 1987/05/23 00:00:00 1100 20

7900 JAMES CLERK 7698 1981/12/03 00:00:00 950 30

7902 FORD ANALYST 7566 1981/12/03 00:00:00 3000 20

7934 MILLER CLERK 7782 1982/01/23 00:00:00 1300 10

14 rows selected.

刪除F1表中10部門的數據:

SQL> delete from f1 where deptno=10;

1 row deleted.

SQL> select * from f1;

DEPTNO DNAME LOC

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

20 RESEARCH DALLAS

30 SALES CHICAGO

40 OPERATIONS BOSTON

SQL> select * from s1;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

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

7369 SMITH CLERK 7902 1980/12/17 00:00:00 800 20

7499 ALLEN SALESMAN 7698 1981/02/20 00:00:00 1600 300 30

7521 WARD SALESMAN 7698 1981/02/22 00:00:00 1250 500 30

7566 JONES MANAGER 7839 1981/04/02 00:00:00 2975 20

7654 MARTIN SALESMAN 7698 1981/09/28 00:00:00 1250 1400 30

7698 BLAKE MANAGER 7839 1981/05/01 00:00:00 2850 30

7782 CLARK MANAGER 7839 1981/06/09 00:00:00 2450

7788 SCOTT ANALYST 7566 1987/04/19 00:00:00 3000 20

7839 KING PRESIDENT 1981/11/17 00:00:00 5000

7844 TURNER SALESMAN 7698 1981/09/08 00:00:00 1500 0 30

7876 ADAMS CLERK 7788 1987/05/23 00:00:00 1100 20

7900 JAMES CLERK 7698 1981/12/03 00:00:00 950 30

7902 FORD ANALYST 7566 1981/12/03 00:00:00 3000 20

7934 MILLER CLERK 7782 1982/01/23 00:00:00 1300

14 rows selected.

SQL> commit;

Commit complete.

結論:在外鍵關聯中使用on delete set null時,刪除父表數據並不會同時刪除與之關聯的子表數據,而是將外鍵關聯字段自動修改成null。

11)外鍵管理存在時,drop父表操作:

create table f1 as select * from dept;

create table s1 as select * from emp;

alter table F1 add constraint PK_F1 primary key (DEPTNO);

alter table S1 add constraint FK_DEPTNO_S1 foreign key (DEPTNO) references F1 (DEPTNO);

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE from user_constraints where table_name in ('S1','F1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT

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

F1 PK_F1 P

S1 FK_DEPTNO_S1 R

刪除F1表:

SQL> drop table F1;

drop table F1

*

ERROR at line 1:

ORA-02449: unique/primary keys in table referenced by foreign keys

SQL> drop table f1 cascade constraint;

Table dropped.

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE from user_constraints where table_name in ('S1','F1');

no rows selected

SQL> select * from tab where tname='S1';

TNAME TABTYPE CLUSTERID

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

S1 TABLE

結論:在drop父表時,如果使用cascade constraint時,會刪除父表同時刪除子表的外鍵約束信息,但是不會刪除子表信息。

二、修改約束

1、為表add約束:

>語法:alter table table_name add constraint

創建測試表:

create table f1 as select * from dept;

create table s1 as select * from emp;

alter table F1 add constraint PK_F1 primary key (DEPTNO);

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE from user_constraints where table_name in ('S1');

no rows selected

此時S1表沒有任何字段。

1)為表S1.EMP添加主鍵約束:

SQL> alter table s1 add constraint pk_s1 primary key (empno);

Table altered.

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE from user_constraints where table_name in ('S1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT

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

S1 PK_S1 P

2)為表S1.SAL增加檢查約束:在表中add約束時首先要保證已有數據沒有違反約束。

SQL> alter table s1 add constraint ck_s1 check(sal > 100);

Table altered.

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE from user_constraints where table_name in ('S1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT

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

S1 CK_S1 C

S1 PK_S1 P

3)增加外鍵約束:

SQL> alter table s1 add constraint fk_s1 foreign key(deptno) references f1(deptno);

Table altered.

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE from user_constraints where table_name in ('S1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT

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

S1 CK_S1 C

S1 FK_S1 R

S1 PK_S1 P

4)增加唯一約束:

SQL> alter table s1 add constraint uk_s1 unique(ename);

Table altered.

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE from user_constraints where table_name in ('S1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT

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

S1 CK_S1 C

S1 FK_S1 R

S1 UK_S1 U

S1 PK_S1 P

5)增加非空約束:不能通過alter table table_name add constraint命令添加,只能通過修改表的方式增加:

SQL> alter table s1 modify(SAL NUMBER(7,2) not null);

Table altered.

create table S1

(

EMPNO NUMBER(4) not null,

ENAME VARCHAR2(10),

JOB VARCHAR2(9),

MGR NUMBER(4),

HIREDATE DATE,

SAL NUMBER(7,2) not null,

COMM NUMBER(7,2),

DEPTNO NUMBER(2)

)

2、啟用/禁用約束

>禁用約束語法:alter table table_name disable constraint cons_name [cascade];

>啟用約束語法:alter table table_name enable constraint cons_name;

1)禁用表S1的約束

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('S1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT STATUS

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

S1 CK_S1 C ENABLED

S1 FK_S1 R ENABLED

S1 UK_S1 U ENABLED

S1 PK_S1 P ENABLED

SQL> ALTER TABLE S1 DISABLE CONSTRAINT CK_S1;

Table altered.

SQL> ALTER TABLE S1 DISABLE CONSTRAINT UK_S1;

Table altered.

SQL> ALTER TABLE S1 DISABLE CONSTRAINT PK_S1;

Table altered.

SQL> ALTER TABLE S1 DISABLE CONSTRAINT FK_S1;

Table altered.

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('S1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT STATUS

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

S1 CK_S1 C DISABLED

S1 FK_S1 R DISABLED

S1 UK_S1 U DISABLED

S1 PK_S1 P DISABLED

2)啟用表S1約束

SQL> ALTER TABLE S1 ENABLE CONSTRAINT PK_S1;

Table altered.

SQL> ALTER TABLE S1 ENABLE CONSTRAINT CK_S1;

Table altered.

SQL> ALTER TABLE S1 ENABLE CONSTRAINT UK_S1;

Table altered.

SQL> ALTER TABLE S1 ENABLE CONSTRAINT FK_S1;

Table altered.

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('S1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT STATUS

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

S1 CK_S1 C ENABLED

S1 FK_S1 R ENABLED

S1 UK_S1 U ENABLED

S1 PK_S1 P ENABLED

3)禁用F1表上的pk_f1約束

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('S1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT STATUS

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

S1 CK_S1 C ENABLED

S1 FK_S1 R ENABLED

S1 UK_S1 U ENABLED

S1 PK_S1 P ENABLED

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('F1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT STATUS

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

F1 PK_F1 P ENABLED

SQL> ALTER TABLE F1 DISABLE CONSTRAINT PK_F1;

ALTER TABLE F1 DISABLE CONSTRAINT PK_F1

*

ERROR at line 1:

ORA-02297: cannot disable constraint (SCOTT.PK_F1) - dependencies exist

注意:此處因為PK_F1存在外鍵約束,所以禁止禁用PK_F1約束。

SQL> ALTER TABLE F1 DISABLE CONSTRAINT PK_F1 CASCADE;

Table altered.

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('F1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT STATUS

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

F1 PK_F1 P DISABLED

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('S1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT STATUS

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

S1 CK_S1 C ENABLED

S1 FK_S1 R DISABLED

S1 UK_S1 U ENABLED

S1 PK_S1 P ENABLED

注意:禁用父表帶有外鍵的約束時,可以采用cascade方式禁用約束,該方式同時也會禁用掉子表的外鍵約束。

3、刪除約束:

語法:alter table table_name drop constraint cons_name [cascade];

1)刪除S1中非外鍵約束

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('S1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT STATUS

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

S1 CK_S1 C ENABLED

S1 FK_S1 R ENABLED

S1 UK_S1 U ENABLED

S1 PK_S1 P ENABLED

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('F1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT STATUS

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

F1 PK_F1 P ENABLED

SQL> ALTER TABLE S1 DROP CONSTRAINT CK_S1;

Table altered.

SQL> ALTER TABLE S1 DROP CONSTRAINT UK_S1;

Table altered.

SQL> ALTER TABLE S1 DROP CONSTRAINT PK_S1;

Table altered.

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('S1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT STATUS

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

S1 FK_S1 R ENABLED

S1 SYS_C0019909 C ENABLED

2)刪除F1表中的pk_f1約束

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('S1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT STATUS

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

S1 FK_S1 R ENABLED

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('F1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT STATUS

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

F1 PK_F1 P ENABLED

SQL> ALTER TABLE F1 DROP CONSTRAINT PK_F1;

ALTER TABLE F1 DROP CONSTRAINT PK_F1

*

ERROR at line 1:

ORA-02273: this unique/primary key is referenced by some foreign keys

注意:不允許刪除帶有外鍵約束的主表約束。

SQL> ALTER TABLE F1 DROP CONSTRAINT PK_F1 CASCADE;

Table altered.

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('F1');

no rows selected

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('S1');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT STATUS

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

no rows selected

注意:cascade刪除父表約束時,會同時刪除子表約束。

三、查看約束信息:

通過user_constraint和user_cons_columns字典表查詢約束信息,同時也以次字典表為基礎編寫約束日常監控腳本:

>CONSTRAINT_TYPE類型:P、R、C、C(not null)、Q

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('EMP');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT STATUS

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

EMP PK_EMP P ENABLED

EMP FK_DEPTNO R ENABLED

SQL> select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS from user_constraints where table_name in ('DEPT');

TABLE_NAME CONSTRAINT_NAME CONSTRAINT STATUS

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

DEPT PK_DEPT P ENABLED


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM