在關係數據庫中,一張表中的每一行數據被稱爲一條記錄。一條記錄就是由多個字段組成的。例如,students
表的兩條記錄:
id | name | score |
---|---|---|
1 | 小明 | 100 |
2 | 小強 | 0 |
每一條記錄都包含若干定義好的字段。同一個表的所有記錄都有相同的字段定義。
主鍵
對於關係表,有個很重要的約束,就是任意兩條記錄不能重複。不能重複不是指兩條記錄不完全相同,而是指能夠通過某個字段唯一區分出不同的記錄,這個字段被稱爲主鍵。
對主鍵的要求,最關鍵的一點是:記錄一旦插入到表中,主鍵最好不要再修改,因爲主鍵是用來唯一定位記錄的,修改了主鍵,會造成一系列的影響。
所以,選取主鍵的一個基本原則是:不使用任何業務相關的字段作爲主鍵。
作爲主鍵最好是完全業務無關的字段,我們一般把這個字段命名爲id
。常見的可作爲id
字段的類型有:
- 自增整數類型:數據庫會在插入數據時自動爲每一條記錄分配一個自增整數,這樣我們就完全不用擔心主鍵重複,也不用自己預先生成主鍵;
- 全局唯一GUID類型:使用一種全局唯一的字符串作爲主鍵。GUID算法通過網卡MAC地址、時間戳和隨機數保證任意計算機在任意時間生成的字符串都是不同的,大部分編程語言都內置了GUID算法,可以自己預算出主鍵。
如果使用INT自增類型,那麼當一張表的記錄數超過2147483647(約21億)時,會達到上限而出錯。使用BIGINT自增類型則可以最多約922億億條記錄。
聯合主鍵
關係數據庫實際上還允許通過多個字段唯一標識記錄,即兩個或更多的字段都設置爲主鍵,這種主鍵被稱爲聯合主鍵。對於聯合主鍵,允許一列有重複,只要不是所有主鍵列都重複即可。
沒有必要的情況下,我們儘量不使用聯合主鍵,因爲它給關係錶帶來了複雜度的上升。
外鍵
當我們用主鍵唯一標識記錄時,我們就可以在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 | 小白 | … |
這樣,我們就可以根據class_id
這個列直接定位出一個students
表的記錄應該對應到classes
的哪條記錄。
在students
表中,通過class_id
的字段,可以把數據與另一張表關聯起來,這種列稱爲外鍵
。
外鍵並不是通過列名實現的,而是通過定義外鍵約束實現的:
ALTER TABLE students
ADD CONSTRAINT fk_class_id
FOREIGN KEY (class_id)
REFERENCES classes (id);
由於外鍵約束會降低數據庫的性能,大部分互聯網應用程序爲了追求速度,並不設置外鍵約束,而是僅靠應用程序自身來保證邏輯的正確性。這種情況下,class_id
僅僅是一個普通的列,只是它起到了外鍵的作用而已。
要刪除一個外鍵約束,也是通過ALTER TABLE
實現的:
ALTER TABLE students
DROP FOREIGN KEY fk_class_id;
注意:刪除外鍵約束並沒有刪除外鍵這一列。
多對多
通過一個表的外鍵關聯到另一個表,我們可以定義出一對多關係。有些時候,還需要定義“多對多”關係。例如,一個老師可以對應多個班級,一個班級也可以對應多個老師,因此,班級表和老師表存在多對多關係。
多對多關係實際上是通過兩個一對多關係實現的,即通過一箇中間表,關聯兩個一對多關係,就形成了多對多關係。
一對一
一對一關係是指,一個表的記錄對應到另一個表的唯一一個記錄。
還有一些應用會把一個大表拆成兩個一對一的表,目的是把經常讀取和不經常讀取的字段分開,以獲得更高的性能。例如,把一個大的用戶表分拆爲用戶基本信息表user_info
和用戶詳細信息表user_profiles
,大部分時候,只需要查詢user_info
表,並不需要查詢user_profiles
表,這樣就提高了查詢速度。