SQL 中的引用完整性完整性检查

Referential completeness integrity check in SQL

我有 3 个表 - usersteamsteam_members。后者是从 team(id)user(id) 的多对多映射(分别是 teamsusers 的外键)。是否有任何完整性检查可以添加到我的数据库中,可以断言虽然没有成员的团队是可能的,但没有团队的用户是不可能的?澄清一下,我想在数据库层强制所有用户必须属于至少 1 个团队(但没有要求所有团队必须有 1 个用户)。在 MYSQL 或 Postgres 中有效的答案是可以接受的。

(答案假定使用 PostgreSQL;如果您使用其他 RDBMS,有关触发器和锁定的详细信息会有所不同,但大多数 RDBMS 应该能够支持相同的底层操作。)

虽然可以将外键从 users 添加到 teams,但这样做需要复制知识 - 除了存在 m:n 关系。这是不可取的。

如果您不需要太多并发,这里最好的选择可能是使用延迟约束触发器和 table 锁定。添加:

  • 延迟约束触发器 ON INSERT OR UPDATE ... FOR EACH ROWusers 上触发执行 LOCK TABLE users, team_members IN EXCLUSIVE MODE 然后检查创建的用户,如果它没有被删除,至少有一个团队通过 team_members 使用加入。您的应用程序在写入之前也需要 LOCK TABLE users IN EXCLUSIVE MODE 以防止死锁。请注意 EXCLUSIVE MODE 不会阻止 SELECT.

  • team_members 上的延迟约束触发器 ON UPDATE OR DELETE ... FOR EACH ROW 以相反的方式执行相同的操作,确保如果您删除团队成员资格,那么曾经是成员的用户仍然有其他团队成员。它还必须同时锁定 usersteam_members.

当然,team_members 也需要对 usersteams 的 FK 约束,但对于 m:n 加入 table 来说应该只是假设。

如果您不介意必须按照特定顺序小心地做事,例如始终在删除旧成员之前添加新成员,您可以使用普通触发器而不是延迟约束触发器。这会在你做错事后立即给你错误,而不是在 COMMIT 时间,但会做出某些语句的顺序,否则这些语句在错误条件下是有效的。

如果您确实需要良好的并发性,那么您可能已经吃饱了。