假设我有两个表parents
和children
。自然地, parent 可能有许多具有一对多关系的 child 。 MySQL 或 PostgreSQL 中是否有任何结构允许限制关联对象的数量,例如:
FOREIGN KEY (parent_id)
REFERENCES parent(id)
LIMIT 3
是否存在类似的东西,或者我们是否需要自定义触发器?
最佳答案
不在外键的定义中。我会通过为每个父级的每个子级添加一个序列号来解决这个问题(PostgreSQL 的代码,主要是标准 SQL):
CREATE TABLE child (
child_id serial PRIMARY KEY
, parent_id int NOT NULL REFERENCES parent
, child_nr int NOT NULL
, CHECK (child_nr BETWEEN 1 AND 3)
, UNIQUE (parent_id, child_nr)
);
通过这种方式,您可以为每位 parent 拥有 1 到 3 个 child ,或者其中一些 child 或没有 child 。但没有其他人。
因为你和(parent_id, child_nr)
有天生的PK现在,您可以删除代理 PK 列 child_id
.但我喜欢为几乎每张表设置一个单列代理 PK ...
您可以使用触发器来限制数量,它会在插入新的之前检查已经有多少 child 。但是你会遇到并发问题,而且它更昂贵、更不可靠、更容易规避并且特定于供应商。
如何管理child_nr
?
RDBMS 只是(可靠地)强制在表中不存在任何非法状态。你怎么算出下child_nr
你决定。许多不同的方法都是可能的。
对于只有三个子项,您可以在创建父项时自动插入所有子项(使用触发器、规则或在您的应用程序中)。给定 (parent_id, child_nr)
和其他列为 NULL。
那么你只允许 UPDATE
而不是 INSERT
或 DELETE
对于子表( GRANT
/REVOKE
),甚至确保使用另一个触发器,以便 super 用户无法绕过它。 FK 到 parent
与 ON DELETE CASCADE
, 所以 child 会自动和 parent 一起死去。
备选
不太可靠,但更便宜:在 parent
中保持 child 的流动计数表并将其限制为 <= 3
.使用 child
中的每个更改更新它带触发器的表。请务必涵盖更改子表中数据的所有可能方法。
关于mysql - 限制数据库级别的关联记录数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26016545/