概念
- 一張表的一個字段受限於另外一張表的一個字段對應的值。這里涉及到兩張表:被引用的表叫主表(父表),另外一張叫從表(子表)。
- 它們的關系:主從表關系(父子表關系)
- 子表:定義了外鍵的表
外鍵的取值要么取父表中字段對應的值,要么取NULL值
嚴重受限於父表
- 父表:被引用的字段要具有唯一性(絕大多數都是用的父表的主鍵)
理論上是可以一張表里的一個字段引用另一個字段,但一般都是用兩張表
外鍵的實現
-
建立表:
先建立父表,后建立子表(因為子表要用到父表)
除非先不考慮外鍵(建完表后再加),表多的時候可以不考慮建表順序。弊端:對數據要求很嚴格,一個垃圾數據都不能放
父表:
create table parent( id number primary key, name varchar2(30), );
子表:
create table child( id number primary key, name varchar2(30), fid number constraint child_fid_fk references parent(id), );
-
插入數據:
一般先插入父表數據,再插入子表數據。除非把子表的外鍵值設置成NULL值,否則會出完整性錯誤。
insert into child values(1, 'test1', 1);
要改為:先加入父表數據
insert into parent values(1, 'p1'); insert into parent values(2, 'p2'); insert into child values(1, 'test1', 1);
-
刪除數據
子表中有關聯的數據,需要先刪子表,后刪父表。
select * from parent;
這里刪除父表的id為2的是沒關系的,只要沒有子表和它關聯就行
有關聯的必須先刪子表的數據,再刪父表的數據
delete from parent where id=1;
-
刪除表
先刪子表,后刪父表
除非使用casecade constraints 解除關聯
drop table parent;
先刪父表會出錯:
有一個被foreign keys關聯的unique/primary key的字段在表中
使用casecade constraints解除關聯就可以刪掉父表
drop table parent cascade constranints;
外鍵的表級約束實現
父表:
create table parent( id number primary key, name varchar2(30), );
子表:
create table child( id number primary key, name varchar2(30), fid number, constraint child_fid_fk foreign key(fid) references parent(id), );
先建立表,后加外鍵
- 子表s_emp :
里面有外鍵dept_id
- 父表s_dept
查看腳本summit2_drop.sql發現:1270行
ALTER TABLE s_emp ADD CONSTRAINT s_emp_dept_id_fk FOREIGN KEY (dept_id) REFERENCES s_dept(id);
級聯刪除和級聯置空
- 級聯刪除:
在外鍵的最后,加上on delete cascade 就是級聯刪除
再刪除主表數據時和主表關聯的子表數據也會刪除
- 級聯置空
在在外鍵的最后,加上on delete set null就是級聯置空
再刪除主表數據時,會把和主表關聯的外鍵設置成NULL
演示:先刪表,不管有沒有
(1)建立一張父表部門表
- id number primart key
- name varchar2(30)
create table mydept( id nimber constraint mydept_pk primary key, name varchar2(30), );
(2)建立一張子表 員工表
- id number primart key
- name varchar2(30)
- dept_id number 外鍵(關聯到部門表)
- salary varchar2(30)
create table mtemp( id number constraint myepm_id_pk primary key, name varchar2(30), salary number, dept_id number constraint myemp_depy_id_fk reference mydept(id) on delete cascade, );
desc mtemp;
(3)分別向兩張表中放入數據
部門表:
insert into mydept values(1, 'test1'); insert into mydept values(2,'test2');
select * from mydept;
員工表:
insert into mtemp values(1, 'empa', 5000,1); insert into mtemp values(2, 'empb', 4500,1); insert into mtemp values(3, 'empc', 5500,1); insert into mtemp values(4, 'empd', 5800,2); insert into mtemp values(5, 'empe', 5100,2);
select * from mtemp;
提交數據:commit;
(4)因為有on delete cascade,所以刪除父表中的id為1的部分是可以的,並不會因為有關聯而刪不掉。
delete from mydept where id=1;
select * from mydept;
select * from mtemp;
(5)如果換為on delete set null,所以刪除父表中的id為1的部分是可以的,而子表的關聯的相應部分置為空
delete from mydept where id=1;
select * from mydept;
select * from mtemp;
注意:如果是windows寫在.sql腳本里,則所有以上的代碼包括commit都寫入,再在cmd切到存放腳本的磁盤(如D)。
用ftp傳到服務器上(192.168.0.26)
- 這里清屏用!cls
- put 要傳送的文件名把文件傳送到服務器
- @要執行的文件名執行文件
- 在SQL>@/user/openlab/要執行的腳本文件