Oracle外鍵約束(Foreign Key)的幾個操作選項
關係型資料庫是以資料表和關係作為兩大對象基礎。資料表是以二維關係將資料群組織在DBMS中,而關係建立資料表之間的關聯,搭建現實物件模型。主外鍵是任何資料庫系統都需存在的約束對象,從物件模型中的商務邏輯加以抽象,作為實體設計的一個部分在資料庫中加以實現。
Oracle外鍵是維護參照完整性的重要手段,大多數情況下的外鍵都是緊密關聯關係。外鍵約束的作用,是保證字表某個欄位取值全都與另一個資料表主鍵欄位相對應。也就是說,只要外鍵約束存在並有效,就不允許無參照取值出現在字表列中。具體在Oracle資料庫中,外鍵約束還是存在一些操作選項的。本篇主要從實驗入手,介紹常見操作選項。
1、環境介紹
筆者選擇Oracle 11gR2進行測試,具體版本號碼為11.2.0.4。
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for 64-bit Windows: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 – Production
建立資料表Prim和Child,對應資料插入。
SQL> create table prim (v_id number(3), v_name varchar2(100));
Table created
SQL> alter table prim add constraint pk_prim primary key (v_id);
Table altered
SQL> create table child (c_id number(3), v_id number(3), c_name varchar2(100));
Table created
SQL> alter table child add constraint pk_child primary key (c_id);
Table altered
二、預設外鍵行為
首先我們查看預設外鍵行為方式。
SQL> alter table CHILD
2 add constraint FK_CHILD_PRIM foreign key (V_ID)
3 references prim (V_ID)
4 ;
在沒有額外參數加入的情況下,Oracle外鍵將嚴格按照標準外鍵方式工作。
--在有子記錄情況下,強制移除主表記錄;
SQL> delete prim where v_id=2;
delete prim where v_id=2
ORA-02292:違反完整約束條件(A.FK_CHILD_PRIM) - 已找到子記錄
--在存在子表記錄情況下,更改主表記錄;
SQL> update prim set v_id=4 where v_id=2;
update prim set v_id=4 where v_id=2
ORA-02292:違反完整約束條件(A.FK_CHILD_PRIM) - 已找到子記錄
--修改子表記錄
SQL> update child set v_id=5 where v_id=2;
update child set v_id=5 where v_id=2
ORA-02291: 違反完整約束條件 (A.FK_CHILD_PRIM) - 未找到父項關鍵字
上面實驗說明:在預設的Oracle外鍵配置條件下,只要有子表記錄存在,主表記錄是不允許修改或者刪除的。子表記錄也必須時刻保證參照完整性。
三、On delete cascade
對於應用開發人員而言,嚴格外鍵約束關係是比較麻煩的。如果直接操作資料庫記錄,就意味著需要手工處理主子表關係,處理刪除順序問題。On delete cascade允許了一種“先刪除主表,連帶刪除子表記錄”的功能,同時確保資料表整體參照完整性。
建立on delete cascade外鍵,只需要在建立外鍵中添加相應的子句。
SQL> alter table child add constraint FK_CHILD_PRIM foreign key(v_id) references prim(v_id) on delete cascade;
Table altered
測試:
SQL> delete prim where v_id=2;
1 row deleted
SQL> select * from prim;
V_ID V_NAME
---- --------------------------------------------------------------------------------
1 kk
3 iowkd
SQL> select * from child;
C_ID V_ID C_NAME
---- ---- --------------------------------------------------------------------------------
1 1 kll
2 1 ddkll
3 1 43kll
SQL> rollback;
Rollback complete
刪除主表操作成功,對應的子表記錄被連帶自動刪除。但是其他動作依然是不允許進行。
SQL> update prim set v_id=4 where v_id=2;
update prim set v_id=4 where v_id=2
ORA-02292:違反完整約束條件(A.FK_CHILD_PRIM) - 已找到子記錄
SQL> update child set v_id=5 where v_id=2;
update child set v_id=5 where v_id=2
ORA-02291: 違反完整約束條件 (A.FK_CHILD_PRIM) - 未找到父項關鍵字
On delete cascade被稱為“串聯刪除”,對開發人員來講是一種方便的策略,可以直接“無視”子記錄而刪掉主記錄。但是,一般情況下,資料庫設計人員和DBA一般都不推薦這樣的策略。
究其原因,還是由於系統商務規則而定。On delete cascade的確在一定程度上很方便,但是這種自動操作在一些業務系統中是可能存在風險的。例如:一個系統中存在一個參數參考關聯性,這個參數被引用到諸如合約的主記錄中。按照商務規則,如果這個參數被引用過,就不應當被刪除。如果我們設定了on delete cascade外鍵,連帶的合約記錄就自動的被“幹掉”了。開發參數模組的同事一般情況下,也沒有足夠的“覺悟”去做手工判定。基於這個因素,我們推薦採用預設的強約束關聯,起碼不會引起資料丟失的情況。
在CentOS 6.4下安裝Oracle 11gR2(x64)
Oracle 11gR2 在VMWare虛擬機器中安裝步驟
Debian 下 安裝 Oracle 11g XE R2
Oracle Linux 6.5安裝Oracle 11.2.0.4 x64
更多詳情見請繼續閱讀下一頁的精彩內容: