SQL中多对多关系必须通过中间表建模,将“多对多”拆为两个“一对多”,中间表含两个外键(如user_id、role_id)并设复合主键或唯一索引,仅在描述关联本身时才加业务字段;查询用JOIN三表(主表A→中间表→主表B),增删改关联数据只操作中间表,须加外键约束和双字段索引以防数据异常与性能问题。
SQL 中多对多关系必须通过中间表(也叫关联表、连接表)建模,不能直接在两个主表之间添加外键。核心思路是:把“多对多”拆解为两个“一对多”,中间用一个独立的第三张表承载关联逻辑。
中间表通常只包含两个外键字段,分别指向两个主表的主键,这两列共同构成复合主键或添加唯一索引,防止重复关联。不建议额外加业务字段,除非该字段描述的是“这次关联本身”的属性(例如:加入时间、角色类型、有效期等)。
user_id, role_id),避免歧义要获取两个主表的关联数据,需用 INNER JOIN 或 LEFT JOIN 连接三张表。顺序一般为:主表 A → 中间表 → 主表 B。

SELECT u.name, r.role_name
FROM users u
INNER JOIN user_roles ur ON u.id = ur.user_id
INNER JOIN roles r ON ur.role_id = r.id;
LEFT JOIN user_roles ur ON u.id = ur.user_id,注意此时
LEFT JOIN roles r ON ur.role_id = r.id
r.role_name 可能为 NULL关联关系的维护不通过修改主表,而是对中间表做 INSERT / DELETE。UPDATE 很少出现,除非中间表存有可变属性(如启用状态)。
INSERT INTO user_roles (user_id, role_id) VALUES (1001, 5);
DELETE FROM user_roles WHERE user_id = 1001 AND role_id = 5;
DELETE FROM user_roles WHERE user_id = 1001;
容易忽略约束完整性与查询效率,导致数据异常或性能下降。