什么是主键
表中经常有一个列或多列的组合,其值能唯一地标识表中的每一行。这样的一列或多列称为表的主键,通过它可强制表的实体完整性。当创建或更改表时可通过定义 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会自动创建外键关联