我有3个表格 - users
,teams
和team_members
。后者是从team(id)
到user(id)
的多对多地图(外键分别为teams
和users
)。是否有任何完整性检查我可以添加到我的数据库,可以断言虽然没有成员的团队是可能的,但没有团队的用户是不可能的?为了澄清,我想在数据库层强制执行所有用户必须属于至少1个团队(而没有要求所有团队必须拥有1个用户)。可以接受在MYSQL或Postgres中有效的答案。
答案 0 :(得分:3)
(答案假定PostgreSQL;如果您使用其他RDBMS,触发器和锁定的详细信息会有所不同,但大多数RDBMS应该能够支持相同的底层操作。)
虽然可以将users
中的外键添加到teams
,但这样做需要重复知识 - 除了现有的m:n之外,你基本上还要创建一个额外的m:1关系。关系。这是不可取的。
如果您不需要太多并发,那么这里最好的选择可能是使用延迟约束触发器和表锁定。添加:
执行ON INSERT OR UPDATE ... FOR EACH ROW
的{{1}}上的延迟约束触发users
触发器,然后检查创建的用户(如果尚未删除)至少具有一个团队通过LOCK TABLE users, team_members IN EXCLUSIVE MODE
使用加入。在写入之前,您的应用程序将需要team_members
以防止死锁。请注意,LOCK TABLE users IN EXCLUSIVE MODE
不会阻止EXCLUSIVE MODE
。
SELECT
上的延迟约束触发器ON UPDATE OR DELETE ... FOR EACH ROW
反向执行相同操作,确保如果删除团队成员身份,那么作为成员的用户仍具有其他团队成员身份。它还必须锁定team_members
和users
。
当然,team_members
还需要team_members
和users
的FK约束,但这应该只适用于m:n连接表。
如果您不介意在特定订单中谨慎处理,例如在删除旧成员资格之前总是添加新成员资格,您可以使用普通触发器而不是延迟约束触发器。这会在你做错事后立即给你错误,而不是在COMMIT时间,但会做出某些在错误条件下有效的语句排序。
如果你确实需要良好的并发性,那么你可能已经填满了。