資料庫中的參照完整性(Foreign Key)
之前在專案中遇到了這樣一個問題,我舉得簡單的例子來說明,
比如我們有兩個表,一個表(department)存放的是部門的資訊,例如部門id,部門名稱等;另一個表是員工表(staff),員工表裡面肯定要存放每個員工所在的部門。那問題來了,如果我們這個時候刪除了部門表中的某條記錄,在staff表中會發生什麼?
為了解答上面的問題,讓我們先來回顧一下什麼是參照完整性。
我們常常希望保證在一個關係中給定屬性集上的取值也在另一個關係的特定屬性集的取值中出現。這種情況稱為參照完整性(referential integrity)
正如我們可以用外碼在SQL中的create table語句一部分的foreign key
例如staff表中的我們可以用 foreign key(dep_name) references department 來表明在每個員工組中指定的部門名稱dep_name必須在department關係中存在。
更一般地,令關係r1和r2的屬性集分別為R1和R2,主碼分別為K1和K2。如果要求對r2中任意元祖t2,均存在r1中元祖t1使得t1.K1 = t2.α,我們稱R2的子集α為參照關係r1中K1的外碼(foreign key)
當我們違反了參照完整性約束時,通常的處理是拒絕執行導致完整性破壞的操作(即進行更新操作的事務被回滾)。但是,在foreign key子句中可以指明:如果被參照關係上的刪除或更新動作違反了約束,那麼系統必須採取一些步驟通過修改參照關係中的元祖來恢復完整性約束,而不是拒絕這樣的操作。
來看下面的例子:
這是我們的department關係
create table department
( dept_name varchar(20),
building varchar(15),
primary key(department)
)
下面一般情況下我們的staff關係
<pre name="code" class="sql">create table staff ( ID varchar(15), name varchar(20), not null dept_name varchar(20), primary key (ID), foreign key(dept_name) reference department )
下面是特定更新動作的staff關係
create table staff
( ID varchar(15),
name varchar(20), not null
dept_name varchar(20),
primary key (ID),
foreign key(dept_name) reference department
on delete cascade
on update cascade
)
由於有了外碼聲名相關聯的on delete cascade子句,如果刪除department中的元祖導致了此參照完整性約束被違反,則刪除並不被系統拒絕,而是對staff關係作聯機刪除,即刪除參照了被刪除系的元祖。類似的,on
update cascade會在更新時同步進行參照關係中元祖的更新。SQL還允許foreign key子句指明除了cascade以外的其他動作,如果約束被違反,可將參考與置為null(用set null代替 cascade),或者置為預設值(set default)。
但是,一般來說,我們習慣的用法是,不允許刪除。如果實在要刪除,可以在被參照關係中加一個欄位,來表明當前的記錄被刪除了,這樣也方便日後查詢等相關操作。