约束与主外键:让数据库守护数据完整性


文档摘要

约束与主外键:让数据库守护数据完整性 仅定义列与类型还不够——你还需要约束(constraint)来规定「什么样的数据是合法的」。约束是数据库层面的规则,会在每次写入或修改时自动校验,拒绝任何违规操作。这一节是表设计中保障数据质量的关键。 为什么需要约束 假设没有任何约束:邮箱可以重复、金额可以是负数、外键可以指向不存在的记录。那么脏数据会迅速积累,应用层要写大量防御性代码,且依然防不胜防。约束的价值在于把规则下沉到数据库,让所有客户端、所有接口共享同一道防线。一次定义,处处生效。 主键约束(Primary Key) 主键用于唯一标识表中的每一行。一张表只能有一个主键,它由一列或多列组成,要求值唯一且不为空。 主键的两个硬性要求: 唯一:任意两行的主键值不能相同。 非空:主键值不能为空。

约束与主外键:让数据库守护数据完整性

仅定义列与类型还不够——你还需要约束(constraint)来规定「什么样的数据是合法的」。约束是数据库层面的规则,会在每次写入或修改时自动校验,拒绝任何违规操作。这一节是表设计中保障数据质量的关键。

为什么需要约束

假设没有任何约束:邮箱可以重复、金额可以是负数、外键可以指向不存在的记录。那么脏数据会迅速积累,应用层要写大量防御性代码,且依然防不胜防。约束的价值在于把规则下沉到数据库,让所有客户端、所有接口共享同一道防线。一次定义,处处生效。

主键约束(Primary Key)

主键用于唯一标识表中的每一行。一张表只能有一个主键,它由一列或多列组成,要求值唯一且不为空。

主键的两个硬性要求:

  • 唯一:任意两行的主键值不能相同。
  • 非空:主键值不能为空。

最常见的做法是用一个 id 列作为主键,类型为 UUID(自动生成)或自增大整数。主键会自动创建索引,因此按主键查找非常快。

外键约束(Foreign Key)

外键用于建立表与表之间的引用关系,并保证引用的有效性。例如订单表中的 user_id 引用用户表的 id,外键约束保证「每个订单对应的用户必须真实存在」。

外键带来的保护包括:

  • 阻止悬挂引用:不能插入一个指向不存在用户的订单。
  • 级联行为:当被引用的行被删除或更新时,可以配置级联策略:
    • CASCADE:连带删除或更新引用它的行(如删除用户时一并删除其订单)。
    • SET NULL:把外键置为空(适用于「解除关联但不删除」的场景)。
    • RESTRICT / NO ACTION:阻止删除,直到先处理掉引用它的行。

外键是关系型数据库表达「关系」并维护一致性的核心机制,是 NoSQL 数据库普遍欠缺的能力。

唯一约束(Unique)

唯一约束保证某一列(或几列的组合)的值在全表范围内不重复。典型场景:

  • 用户表的 email 必须唯一,防止重复注册。
  • 商品的 slug(网址中的标识)必须唯一。

唯一约束允许多个空值(NULL 不算重复),这一点在实际使用时要留意。

非空约束(Not Null)

非空约束要求某列必须有值,不能为空。它常与数据类型配合,进一步收紧合法性。例如订单的 amount 既要是数值,又不能为空。

经验法则:默认给字段加非空约束,只有在确实需要「未知 / 可选」语义时才允许为空。空值会增加查询与逻辑处理的复杂度。

检查约束(Check)

检查约束允许你用任意布尔表达式自定义规则,非常灵活。例如:

  • 金额 amount >= 0:金额不能为负。
  • 订单状态只能是预定义的几个值。
  • 结束时间必须晚于开始时间。

检查约束是兜底的「业务规则防线」,能拦截那些类型与外键都管不到的逻辑错误。

默认值(Default)

默认值不是严格意义上的约束,但常与约束配合。当插入数据时若未提供某列的值,则使用默认值。典型用法:

  • created_at 默认为当前时间(now())。
  • 主键 id 默认为自动生成的 UUID。
  • published 默认为「假」。

善用默认值,能让插入操作更简洁,并保证关键字段不会因为遗漏而为空。

约束的组合示例

仍以文章表为例,综合各类约束后,它应满足:

  • id 为主键(唯一且非空)
  • author_id 为外键,关联用户表,作者被删除时级联处理其文章
  • title 非空(必须有标题)
  • slug 唯一(网址标识不能重复)
  • published 默认为「假」
  • word_count >= 0(字数不能为负,通过检查约束)

这套约束共同确保:每篇文章有唯一标识、有合法作者、有标题、网址标识不重复、关键数值合法。无论哪个客户端写入数据,数据库都会强制执行这些规则。

约束与性能的取舍

约束会在每次写入时增加校验开销,但这个代价几乎总是值得的——它换来的是数据质量的保障。唯一需要注意的:

  • 外键会带来级联操作的开销,在海量写入场景需谨慎设计级联策略。
  • 检查约束中的复杂表达式可能影响写入性能,应保持表达式简洁。

对于绝大多数应用,正确使用约束的收益远大于性能损耗。

小结

约束是数据库守护数据完整性的「规则层」:主键保证唯一标识,外键保证关系有效,唯一约束防止重复,非空约束防止遗漏,检查约束表达业务规则,默认值简化写入。把它们用足,你的数据就会自带一道坚实的防线。下一节我们把视角放大,讨论如何用主外键设计表与表之间的关系。


发布者: 作者: 灏天文库 转发
评论区 (0)
U