數據庫的主鍵和外鍵詳解

MySQL數據庫的主鍵和外鍵詳解

主鍵

主鍵的定義

主鍵:表中常常有一個列或多列的組合,其值能惟一地標識表中的每一行。這樣的一列或多列稱爲表的主鍵,經過它可強制表的實體完整性。當建立或更改表時可經過定義 PRIMARY KEY 約束來建立主鍵。一個表只能有一個 PRIMARY KEY 約束,並且 PRIMARY KEY 約束中的列不能接受空值。因爲 PRIMARY KEY 約束確保惟一數據,因此常常用來定義標識列。mysql

做用:算法

1)保證明體的完整性;sql

2)加快數據庫的操做速度數據庫

3)在表中添加新記錄時,DBMS會自動檢查新記錄的主鍵值,不容許該值與其餘記錄的主鍵值重複。編程

4)DBMS自動按主鍵值的順序顯示錶中的記錄。若是沒有定義主鍵,則按輸入記錄的順序顯示錶中的記錄。編程語言

聯合主鍵性能

關係數據庫實際上還容許經過多個字段惟一標識記錄,即兩個或更多的字段都設置爲主鍵,這種主鍵被稱爲聯合主鍵。code

對於聯合主鍵,容許一列有重複,只要不是全部主鍵列都重複便可。blog

主鍵的特性

主鍵的必要性圖片

在有些數據庫中,雖然主鍵不是必需的,但最好爲每一個表都設置一個主鍵,不論是單主鍵仍是複合主鍵。它存在表明着表結構的完整性,表的記錄必須得有惟一區分的字段,主鍵主要是用於其餘表的外鍵關聯,以及本記錄的修改與刪除。

主鍵的無心義性

因爲主鍵的做用十分重要,如何選取主鍵會對業務開發產生重要影響。若是咱們以學生的身份證號做爲主鍵,彷佛能惟必定位記錄。然而,身份證號也是一種業務場景,若是身份證號升位了,或者須要變動,做爲主鍵,不得不修改的時候,就會對業務產生嚴重影響。

選取主鍵的一個基本原則是:不使用任何業務相關的字段做爲主鍵。

所以,身份證號、手機號、郵箱地址這些看上去能夠惟一的字段,均不可用做主鍵。

主鍵的選擇

  • 自增整數類型:數據庫會在插入數據時自動爲每一條記錄分配一個自增整數,這樣咱們就徹底不用擔憂主鍵重複,也不用本身預先生成主鍵;
  • 全局惟一GUID類型:使用一種全局惟一的字符串做爲主鍵,相似8f55d96b-8acc-4636-8cb8-76bf8abc2f57。GUID算法經過網卡MAC地址、時間戳和隨機數保證任意計算機在任意時間生成的字符串都是不一樣的,大部分編程語言都內置了GUID算法,能夠本身預算出主鍵。

對於大部分應用來講,一般自增類型的主鍵就能知足需求

定義的自增性整數類型的主鍵通常使用是BIGINT NOT NULL AUTO_INCREMENT類型。

若是使用INT自增類型,那麼當一張表的記錄數超過2147483647(約21億)時,會達到上限而出錯。使用BIGINT自增類型則能夠最多約922億億條記錄。

外鍵

外鍵的定義

若是公共關鍵字在一個關係中是主關鍵字,那麼這個公共關鍵字被稱爲另外一個關係的外鍵。因而可知,外鍵表示了兩個關係之間的相關聯繫。以另外一個關係的外鍵做主關鍵字的表被稱爲主表,具備此外鍵的表被稱爲主表的從表。外鍵又稱做外關鍵字。

舉例:

student表:
在這裏插入圖片描述
class表:
在這裏插入圖片描述
因爲一個班級能夠有多個學生,在關係模型中,這兩個表的關係能夠稱爲「一對多」,即一個class的記錄能夠對應多個student表的記錄。

爲了表達這種一對多的關係,咱們須要在student表中加入一列class_id,讓它的值與class表的某條記錄相對應。

這樣,咱們就能夠根據class_id這個列直接定位出一個student表的記錄應該對應到class的哪條記錄。

student表中,經過class_id的字段,能夠把數據與另外一張表關聯起來,這種列稱爲外鍵

外鍵並非經過列名實現的,而是經過定義外鍵約束實現的:

//定義外鍵約束
ALTER TABLE student
ADD CONSTRAINT fk_class_id  //外鍵約束的名稱fk_class_id能夠任意
FOREIGN KEY (class_id)     //指定了class_id做爲外鍵
REFERENCES class (id);    //指定了這個外鍵將關聯到class表的id列(即class表的主鍵)

class_id爲學生表的外鍵。(此時student表中的class_id與class表中的id表示的含義相同)

此時外鍵表是student表,主鍵表是class表。

要刪除一個外鍵約束,也是經過ALTER TABLE實現的:

ALTER TABLE student
DROP FOREIGN KEY fk_class_id;

因爲外鍵約束會下降數據庫的性能,大部分互聯網應用程序爲了追求速度,並不設置外鍵約束,而是僅靠應用程序自身來保證邏輯的正確性。這種狀況下,class_id僅僅是一個普通的列,只是它起到了外鍵的做用而已。

選取設置 MySQL 外鍵的字段

定義一個外鍵時,須要遵照下列規則:

  • 父表必須已經存在於數據庫中,或者是當前正在建立的表。若是是後一種狀況,則父表與子表是同一個表,這樣的表稱爲自參照表,這種結構稱爲自參照完整性。
  • 必須爲父表定義主鍵。
  • 主鍵不能包含空值,但容許在外鍵中出現空值。也就是說,只要外鍵的每一個非空值出如今指定的主鍵中,這個外鍵的內容就是正確的。
  • 在父表的表名後面指定列名或列名的組合。這個列或列的組合必須是父表的主鍵或候選鍵。
  • 外鍵中列的數目必須和父表的主鍵中列的數目相同。
  • 外鍵中列的數據類型必須和父表主鍵中對應列的數據類型相同。

外鍵的做用

保持數據一致性,完整性。主要目的是控制存儲在外鍵表中的數據。 使兩張表造成關聯,外鍵只能引用外表中的列的值或使用空值

外鍵約束

MySQL外鍵約束(FOREIGN KEY)用來在兩個表的數據之間創建連接,它能夠是一列或者多列。一個表能夠有一個或多個外鍵。

外鍵是表的一個字段,不是本表的主鍵,但對應另外一個表的主鍵。定義外鍵後,不容許刪除另外一個表中具備關聯關係的行。

  • 主表(父表)

    對於兩個具備關聯關係的表而言,相關聯字段中主鍵所在的表就是主表。

    被引用的表叫主表(父表)。

  • 從表(子表)

    對於兩個具備關聯關係的表而言,相關聯字段中外鍵所在的表就是從表。

    定義了外鍵的表叫從表(子表)。

外鍵約束的做用:

阻止執行

  • 從表插入新行,其外鍵值不是主表的主鍵值便阻止插入;
  • 從表修改外鍵值,新值不是主表的主鍵值便阻止修改;
  • 主表刪除行,其主鍵值在從表裏存在便阻止刪除(要想刪除,必須先刪除從表的相關行);
  • 主表修改主鍵值,舊值在從表裏存在便阻止修改(要想修改,必須先刪除從表的相關行)。

級聯執行

  • 主表刪除行,連帶從表的相關行一塊兒刪除;
  • 主表修改主鍵值,連帶從表相關行的外鍵值一塊兒修改。兩種方法提供給用戶選擇。不管選取哪一種方法,從表裏都不會有多餘行。從另外一個角度理解,用拒絕同一事物在從表中的標誌與主表不一致來實現與主表中的標誌一致。

兩種實現方法,經過下面方式選擇:

  • 界面:設級聯更新、級聯刪除兩個選擇方框,選取則級聯執行、不選取則阻止執行;
  • 命令:設E)kSCM)E、RESTRICT兩個可選項,CASCADE爲級聯執行、RESTRICT爲阻止執行。

CASCADE:級聯刪除

在外鍵表的最後,加上on delete cascade 就是級聯刪除

再刪除主表數據時和主表關聯的子表數據也會刪除

CREATE TABLE `student` (
  `id` bigint(64) NOT NULL AUTO_INCREMENT,
  `class_id` bigint(64) DEFAULT NULL,
  `name` varchar(32) COLLATE utf8_bin DEFAULT NULL,
  `age` int(32) DEFAULT NULL,
  `sex` varchar(32) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_class_id` (`class_id`),
  CONSTRAINT `fk_class_id` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`)  
    on delete cascade,
)

所謂的級聯刪除,就是刪除主鍵表的同時,外鍵表同時刪除。

以上面的例子將就是,假如班級表中的某個班級被刪除了,那麼在學生表中要想查詢這個被刪除的班級號所對應的班級信息就會報錯,由於已經不存在這個班級了,因此,刪除班級表(主鍵表)時必須刪除其餘與之關聯的表,這裏就說明了外鍵的做用,保持數據的一致性、完整性。固然反過來說,你刪除學生表中的記錄,並不影響班級表中的數據,你查詢班級號也能正確查詢。因此刪除外鍵表中的數據並不影響主鍵表。

RESTRICT:約束/限制、NO ACTION(非活動,默認)

當取值爲No Action或者Restrict時,則當在主鍵表中刪除對應記錄時,首先檢查該記錄是否有對應外鍵,若是有則不容許刪除。(即外鍵表約束主鍵表)

SET NULL:級聯置空

在在外鍵表的最後,加上on delete set null就是級聯置空

再刪除主表數據時,會把和主表關聯的外鍵設置成NULL

CREATE TABLE `student` (
  `id` bigint(64) NOT NULL AUTO_INCREMENT,
  `class_id` bigint(64) DEFAULT NULL,
  `name` varchar(32) COLLATE utf8_bin DEFAULT NULL,
  `age` int(32) DEFAULT NULL,
  `sex` varchar(32) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_class_id` (`class_id`),
  CONSTRAINT `fk_class_id` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`)  
   on  delete  set null,
)

當取值爲Set Null時,則當在主鍵表中刪除對應記錄時,首先檢查該記錄是否有對應外鍵,若是有則設置子表中該外鍵值爲null,(同樣是外鍵表約束主鍵表,不過這就要求該外鍵容許取null)。

NO ACTION和RESTRICT的區別:只有在及個別的狀況下會致使區別,前者是在其餘約束的動做以後執行,後者具備最高的優先權執行。

注意

刪除表時,應該先刪子表,後刪父表,除非使用casecade constraints 解除關聯。

先刪除父表時會報錯:有一個被foreign keys關聯的 key的字段在子表中

<e>查詢:drop table class

錯誤代碼: 3730
Cannot drop table 'class' referenced by a foreign key constraint 'fk_class_id' on table 'student'.

若是必定要先刪除父表

使用casecade constraints解除關聯就能夠刪掉父表

drop table parent cascade constranints;

在這裏插入圖片描述

若有須要的朋友能夠關注個人公衆號並回復:數據庫電子書 ,便可獲取如下免費PDF資料
在這裏插入圖片描述

相關文章
相關標籤/搜索