什么是主鍵
表中經常有一個列或多列的組合,其值能唯一地標識表中的每一行。這樣的一列或多列稱為表的主鍵,通過它可強制表的實體完整性。當創建或更改表時可通過定義 PRIMARY KEY 約束來創建主鍵。一個表只能有一個 PRIMARY KEY 約束,而且 PRIMARY KEY 約束中的列不能接受空值。由於 PRIMARY KEY 約束確保唯一數據,所以經常用來定義標識列。
選取主鍵的一個基本原則
不使用任何業務相關的字段作為主鍵。
因此,身份證號、手機號、郵箱地址這些看上去可以唯一的字段,均不可用作主鍵。
主鍵的選擇
- 自增整數類型:數據庫會在插入數據時自動為每一條記錄分配一個自增整數,這樣我們就完全不用擔心主鍵重復,也不用自己預先生成主鍵;
- 全局唯一GUID類型:使用一種全局唯一的字符串作為主鍵,類似
8f55d96b-8acc-4636-8cb8-76bf8abc2f57
。GUID算法通過網卡MAC地址、時間戳和隨機數保證任意計算機在任意時間生成的字符串都是不同的,大部分編程語言都內置了GUID算法,可以自己預算出主鍵。
什么是外鍵
如果公共關鍵字在一個關系中是主關鍵字,那么這個公共關鍵字被稱為另一個關系的外鍵。由此可見,外鍵表示了兩個關系之間的相關聯系。以另一個關系的外鍵作主關鍵字的表被稱為主表,具有此外鍵的表被稱為主表的從表。外鍵又稱作外關鍵字。
例子
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
表。
設置外鍵的要求
- 兩張數據表的數據引擎必須一致
- 父表中相關的id必須存在
- 兩個字段類型必須一樣,即
FOREIGN KEY (class_id) REFERENCES class (id);
中class_id
和id
數據類型必須一致 - 不能既是主鍵,又是外鍵
不滿足上述條件會報錯Cannot add foreign key constraint
在gorm中如何設置外鍵
假設categories為主表,posts為從表,則在posts的model中,需要定義一個CategoryID字段,並定義Category字段:
type Post struct {
ID uuid.UUID `json:"id" gorm:"type:char(36);primary_key"`
CategoryId uint `json:"category_id" gorm:"not null"` //這是外鍵,與Category關聯。必須命名為CategoryId或CategoryID
Category *Category //必須命名為Category
Content string
}
這樣gorm會自動創建外鍵關聯