标准答案

  1. 一对一可在附表放一个带 UNIQUE 约束的外键,例如用户与可选实名认证资料,避免主表塞入大量低频或敏感字段。
  2. 一对多把外键放在多的一侧,例如订单表持有 user_id;索引通常围绕外键加常见筛选或排序字段设计。
  3. 多对多通过中间表实现,例如 user_role(user_id, role_id),中间表应有联合唯一约束防止重复关联。
  4. 如果关系本身有状态、创建人、排序或有效期,中间表不是简单连接表,而是需要独立建模的业务实体。
  5. 删除和更新规则要与业务生命周期一致,不要仅靠 ORM 自动级联决定数据命运。

题目解析

关系基数描述的是业务约束,不是页面当前恰好展示了几个字段。例如一个用户“目前只有一个默认地址”不代表用户与地址是一对一,地址仍然是典型一对多关系,默认地址只是额外的选择规则。

中间表往往会随着业务成长。用户与课程的选课关系一旦需要保存报名时间、学习进度、状态和来源,就应把这些字段放在 enrollment 这样的关系实体中,而不是继续把信息塞回任一主表。

代码示例

用户与角色通过关系表关联,联合主键或联合唯一键保证同一个角色不会被重复授予。

sql
CREATE TABLE user_role (
  user_id BIGINT NOT NULL,
  role_id BIGINT NOT NULL,
  granted_at TIMESTAMP NOT NULL,
  PRIMARY KEY (user_id, role_id),
  FOREIGN KEY (user_id) REFERENCES users(id),
  FOREIGN KEY (role_id) REFERENCES roles(id)
);

常见误区

  • 把多对多关系存成逗号分隔的 ID 字符串,导致约束、索引和查询都失效。
  • 在一对多子表缺少外键索引,父对象列表一多就频繁扫描整张子表。

作者信息