SQL初認識——7:外鍵

一:

一對多

當我們用主鍵唯一標識記錄時,我們就可以在students表中確定任意一個學生的記錄:

id name other columns...

1 小明 ...

2 小紅 ...

我們還可以在classes表中確定任意一個班級記錄:

id name other columns...

1 一班 ...

2 二班 ...

但是我們如何確定students表的一條記錄,例如,id=1的小明,屬于哪個班級呢?

由于一個班級可以有多個學生,在關系模型中,這兩個表的關系可以稱為“一對多”,即一個classes的記錄可以對應多個students表的記錄。

為了表達這種一對多的關系,我們需要在students表中加入一列class_id,讓它的值與classes表的某條記錄相對應:

id class_id name other columns...

1 1 小明 ...

2 1 小紅 ...

5 2 小白 ...

這樣,我們就可以根據(jù)class_id這個列直接定位出一個students表的記錄應該對應到classes的哪條記錄。

例如:

小明的class_id是1,因此,對應的classes表的記錄是id=1的一班;

小紅的class_id是1,因此,對應的classes表的記錄是id=1的一班;

小白的class_id是2,因此,對應的classes表的記錄是id=2的二班。

在students表中,通過class_id的字段,可以把數(shù)據(jù)與另一張表關聯(lián)起來,這種列稱為外鍵。

外鍵并不是通過列名實現(xiàn)的,而是通過定義外鍵約束實現(xiàn)的:

ALTER TABLE students

ADD CONSTRAINT fk_class_id

FOREIGN KEY (class_id)

REFERENCES classes (id);

其中,外鍵約束的名稱fk_class_id可以任意,F(xiàn)OREIGN KEY (class_id)指定了class_id作為外鍵,REFERENCES classes (id)指定了這個外鍵將關聯(lián)到classes表的id列(即classes表的主鍵)。

通過定義外鍵約束,關系數(shù)據(jù)庫可以保證無法插入無效的數(shù)據(jù)。即如果classes表不存在id=99的記錄,students表就無法插入class_id=99的記錄。

由于外鍵約束會降低數(shù)據(jù)庫的性能,大部分互聯(lián)網(wǎng)應用程序為了追求速度,并不設置外鍵約束,而是僅靠應用程序自身來保證邏輯的正確性。這種情況下,class_id僅僅是一個普通的列,只是它起到了外鍵的作用而已。

要刪除一個外鍵約束,也是通過ALTER TABLE實現(xiàn)的:

ALTER TABLE students

DROP FOREIGN KEY fk_class_id;

注意:刪除外鍵約束并沒有刪除外鍵這一列。刪除列是通過DROP COLUMN ...實現(xiàn)的。

多對多

通過一個表的外鍵關聯(lián)到另一個表,我們可以定義出一對多關系。有些時候,還需要定義“多對多”關系。例如,一個老師可以對應多個班級,一個班級也可以對應多個老師,因此,班級表和老師表存在多對多關系。

多對多關系實際上是通過兩個一對多關系實現(xiàn)的,即通過一個中間表,關聯(lián)兩個一對多關系,就形成了多對多關系:

teachers表:

id name

1 張老師

2 王老師

3 李老師

4 趙老師

classes表:

id name

1 一班

2 二班

中間表teacher_class關聯(lián)兩個一對多關系:

id teacher_id class_id

1 1 1

2 1 2

3 2 1

4 2 2

5 3 1

6 4 2

通過中間表teacher_class可知teachers到classes的關系:

id=1的張老師對應id=1,2的一班和二班;

id=2的王老師對應id=1,2的一班和二班;

id=3的李老師對應id=1的一班;

id=4的趙老師對應id=2的二班。

同理可知classes到teachers的關系:

id=1的一班對應id=1,2,3的張老師、王老師和李老師;

id=2的二班對應id=1,2,4的張老師、王老師和趙老師;

因此,通過中間表,我們就定義了一個“多對多”關系。

3:

一對一

一對一關系是指,一個表的記錄對應到另一個表的唯一一個記錄。

例如,students表的每個學生可以有自己的聯(lián)系方式,如果把聯(lián)系方式存入另一個表contacts,我們就可以得到一個“一對一”關系:

id student_id mobile

1 1 135xxxx6300

2 2 138xxxx2209

3 5 139xxxx8086

有細心的童鞋會問,既然是一對一關系,那為啥不給students表增加一個mobile列,這樣就能合二為一了?

如果業(yè)務允許,完全可以把兩個表合為一個表。但是,有些時候,如果某個學生沒有手機號,那么,contacts表就不存在對應的記錄。實際上,一對一關系準確地說,是contacts表一對一對應students表。

還有一些應用會把一個大表拆成兩個一對一的表,目的是把經(jīng)常讀取和不經(jīng)常讀取的字段分開,以獲得更高的性能。例如,把一個大的用戶表分拆為用戶基本信息表user_info和用戶詳細信息表user_profiles,大部分時候,只需要查詢user_info表,并不需要查詢user_profiles表,這樣就提高了查詢速度。

4:

小結

關系數(shù)據(jù)庫通過外鍵可以實現(xiàn)一對多、多對多和一對一的關系。外鍵既可以通過數(shù)據(jù)庫來約束,也可以不設置約束,僅依靠應用程序的邏輯來保證。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 我們已經(jīng)知道,關系數(shù)據(jù)庫是建立在關系模型上的。而關系模型本質上就是若干個存儲數(shù)據(jù)的二維表,可以把它們看作很多Exc...
    章逸佳閱讀 557評論 0 0
  • 簡介 MyBatis[http://www.mybatis.org/mybatis-3] 是一款優(yōu)秀的持久層框架,...
    Whyn閱讀 1,143評論 0 0
  • 一. Java基礎部分.................................................
    wy_sure閱讀 4,038評論 0 11
  • 1.數(shù)據(jù)庫簡介 人類在進化的過程中,創(chuàng)造了數(shù)字、文字、符號等來進行數(shù)據(jù)的記錄,但是承受著認知能力和創(chuàng)造能力的提升,...
    大熊_7d48閱讀 608評論 0 1
  • 我在幾個月前因緣際會參加了一個閱讀課程的學習,并因此結識了一些讀友,建立了兩個讀書群。現(xiàn)在有個群運行得很好,...
    韻兒吉祥閱讀 165評論 0 0

友情鏈接更多精彩內容