定義
設(shè)F是基本關(guān)系R的一個(gè)或一組屬性,但不是關(guān)系的鍵,Ks是基本關(guān)系S的主鍵。如果F與Ks相對(duì)應(yīng),則稱(chēng)F是R的外鍵,并稱(chēng)基本關(guān)系R為參照關(guān)系,基本關(guān)系S為被參照關(guān)系或目標(biāo)關(guān)系。
換而言之,如果關(guān)系模式R中的某屬性集不是R的主鍵,而是另一個(gè)關(guān)系R1的主鍵則該屬性集是關(guān)系模式R的外鍵,通常在數(shù)據(jù)庫(kù)設(shè)計(jì)中縮寫(xiě)為FK。
在實(shí)際操作中,將一個(gè)表的值放入第二個(gè)表來(lái)表示關(guān)聯(lián),所使用的值是第一個(gè)表的主鍵值(在必要時(shí)可包括復(fù)合主鍵值)。此時(shí),第二個(gè)表中保存這些值的屬性稱(chēng)為外鍵(foreign key)。1
顯然目標(biāo)關(guān)系的主碼和參照關(guān)系的外碼必須定義在一個(gè)或同一組的域上。關(guān)系R和S不一定是不同的關(guān)系,即外鍵不一定要與相應(yīng)的主鍵同名。如在學(xué)生(學(xué)號(hào),姓名,性別,專(zhuān)業(yè)號(hào),年齡,班長(zhǎng))關(guān)系中,“學(xué)號(hào)”是主鍵,“班長(zhǎng)”屬性表示該學(xué)生所在班級(jí)的班長(zhǎng)的學(xué)號(hào),它引用了本關(guān)系中“學(xué)號(hào)”屬性,因此“班長(zhǎng)”是外鍵,這里學(xué)生關(guān)系既是參照關(guān)系也是被參照關(guān)系。不過(guò)在實(shí)際應(yīng)用中為了便于識(shí)別,當(dāng)主鍵與相應(yīng)的外鍵屬于不同關(guān)系時(shí),往往取相同的名字。2
作用保持?jǐn)?shù)據(jù)一致性,完整性,主要目的是控制存儲(chǔ)在外鍵表中的數(shù)據(jù)。 使兩張表形成關(guān)聯(lián),外鍵只能引用外表中的列的值或使用空值。3
如果不使用外鍵,表2的學(xué)號(hào)字段插了一個(gè)值(比如20140999999),但是這個(gè)值在表1中并沒(méi)有,這個(gè)時(shí)候,數(shù)據(jù)庫(kù)允許插入,并不會(huì)對(duì)插入的數(shù)據(jù)做關(guān)系檢查。然而在設(shè)置外鍵的情況下,你插入表2學(xué)號(hào)字段的值必須要求在表1的學(xué)號(hào)字段能找到。 同時(shí),如果你要?jiǎng)h除表1的某個(gè)學(xué)號(hào)字段,必須保證表2中沒(méi)有引用該字段值的列,否則就沒(méi)法刪除。這就是所謂的保持?jǐn)?shù)據(jù)的一致性和完整性。如右圖,如果表2還引用表1的某個(gè)學(xué)號(hào),你卻把表1中的這個(gè)學(xué)號(hào)刪了,表2就不知道這個(gè)學(xué)號(hào)對(duì)應(yīng)的學(xué)生是哪個(gè)學(xué)生。
數(shù)據(jù)庫(kù)中的表必須符合規(guī)范,才能杜絕數(shù)據(jù)冗余、插入異常、刪除異常等現(xiàn)象。規(guī)范的過(guò)程是分解表的過(guò)程。經(jīng)過(guò)分解,伺一事物的代表屬性出現(xiàn)在不同的表中。顯然,它們應(yīng)該保持一致。例如,某學(xué)生的代表數(shù)據(jù)是學(xué)號(hào)012,在學(xué)生表里是012,在成績(jī)表里也應(yīng)該是012。這種一致性由外鍵實(shí)現(xiàn)。外鍵的功能是:它的值一定是另一個(gè)表的主鍵值。學(xué)號(hào)在學(xué)生表里是主鍵,在成績(jī)表里是外鍵。成績(jī)表里的學(xué)號(hào)一定要是學(xué)生表里的學(xué)號(hào)。于是,學(xué)生表里的學(xué)號(hào)和成績(jī)表里的學(xué)號(hào)就一致了。可以直觀地理解,外鍵的功能是實(shí)現(xiàn)同一事物在不同表中的標(biāo)志一致性。2功能的實(shí)現(xiàn)由外鍵聯(lián)系的兩個(gè)表,在單獨(dú)操作時(shí),外鍵功能由兩種方法實(shí)現(xiàn)4:
阻止執(zhí)行
從表插入新行,其外鍵值不是主表的主鍵值便阻止插入;
從表修改外鍵值,新值不是主表的主鍵值便阻止修改;
主表刪除行,其主鍵值在從表里存在便阻止刪除(要想刪除,必須先刪除從表的相關(guān)行);
主表修改主鍵值,舊值在從表里存在便阻止修改(要想修改,必須先刪除從表的相關(guān)行)。
級(jí)聯(lián)執(zhí)行
主表刪除行,連帶從表的相關(guān)行一起刪除;
主表修改主鍵值,連帶從表相關(guān)行的外鍵值一起修改。兩種方法提供給用戶(hù)選擇。無(wú)論選取哪種方法,從表里都不會(huì)有多余行。從另一個(gè)角度理解,用拒絕同一事物在從表中的標(biāo)志與主表不一致來(lái)實(shí)現(xiàn)與主表中的標(biāo)志一致。
兩種實(shí)現(xiàn)方法,通過(guò)下面方式選擇:
界面:設(shè)級(jí)聯(lián)更新、級(jí)聯(lián)刪除兩個(gè)選擇方框,選取則級(jí)聯(lián)執(zhí)行、不選取則阻止執(zhí)行;
命令:設(shè)E)kSCM)E、RESTRICT兩個(gè)可選項(xiàng),CASCADE為級(jí)聯(lián)執(zhí)行、RESTRICT為阻止執(zhí)行。
應(yīng)用示例student(s#,sname,d#),即學(xué)生這個(gè)關(guān)系有三個(gè)屬性:學(xué)號(hào),姓名,所在系別。
dep(d#,dname),即院系有兩個(gè)屬性:系號(hào)、系名。
則s#、d#是主鍵,也是各自所在關(guān)系的唯一候選鍵,d#是student的外鍵。
建立外鍵的前提: 本表的列必須與外鍵類(lèi)型相同(外鍵必須是外表主鍵)。
指定外鍵關(guān)鍵字: foreign key(列名)
引用外鍵關(guān)鍵字: references (主表主鍵)
事件觸發(fā)限制: on delete和on update , 可設(shè)參數(shù)cascade(跟隨外鍵改動(dòng)), restrict(限制外表中的外鍵改動(dòng)),set Null(設(shè)空值),set Default(設(shè)默認(rèn)值),[默認(rèn)]no action
例如:
outTable表主鍵id 類(lèi)型 int
創(chuàng)建含有外鍵的表:
create table temp(
id int,
name char(20),
foreign key(id) references outTable(id) on delete cascade on update cascade);
說(shuō)明:把id列 設(shè)為外鍵 參照外表outTable的id列 當(dāng)外鍵的值刪除 本表中對(duì)應(yīng)的列刪除 當(dāng)外鍵的值改變 本表中對(duì)應(yīng)的列值改變。
注:在創(chuàng)建表中增加外鍵的觸發(fā)事件是不行的,
create table temp(
id int,
name char(20),
foreign key(id) references outTable(id));
使用原則1、 為關(guān)聯(lián)字段創(chuàng)建外鍵。
2、 所有的鍵都必須唯一。
3、避免使用復(fù)合鍵。
4、外鍵總是關(guān)聯(lián)唯一的鍵字段。
使用方法主鍵表和外建表:
使用設(shè)計(jì)界面創(chuàng)建外鍵時(shí),出現(xiàn)主鍵表和外建表問(wèn)題,上述使個(gè)人理解有誤:
CREATE TABLE TABLE1
(
[ID] INT IDENTITY(1,1) PRIMARY KEY
)
GO
CREATE TABLE TABLE2
(
[ID] INT NOT NULL,
FOREIGN KEY ([ID]) REFERENCES [TABLE1]([ID])
)
GO
TABLE2 中引用了TABLE1,在此TABLE1為主鍵表,而TABLE2 為外鍵表。
總結(jié):主鍵表是被引用的表,外鍵表是引用其他表的表。
有效性有很多時(shí)候,程序員會(huì)發(fā)現(xiàn)字段缺少、多余問(wèn)題或者是創(chuàng)建外鍵以后就不能添加沒(méi)有受約束的行[特殊情況下是有必要的],這個(gè)時(shí)候不想對(duì)表結(jié)構(gòu)進(jìn)行操作,就可以使用約束失效。
以 Northwind 為例:想給產(chǎn)品表【Products表】添加一條不受種類(lèi)表【Categories表】限制的數(shù)據(jù)。可以使產(chǎn)品表中的 Categories 約束失效。
寫(xiě)法:ALTER TABLE dbo.Products NOCHECKCONSTRAINT FK_Products_Categories
添加完成后再使其有效:
ALTER TABLE dbo.Products CHECK CONSTRAINT FK_Products_Categories
這樣就完成不受某表約束的數(shù)據(jù)添加了。
還有一個(gè)好處是:如上述例子。修改 Categories 表時(shí) 添加字段時(shí) 要把所有引用 Categories 表的外鍵給失效。等給 Categories 表添加字段完成后再使所有應(yīng)用 Categories 表的外鍵恢復(fù)有效性即可。