不在外键的定义中。我会通过像这样为每个父母的每个孩子添加一个序列号来解决这个问题(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)
);
通过这种方式,您可以为每个父母生 1 到 3 个孩子,或者其中一些孩子或没有孩子。但没有其他人。
由于您现在与(parent_id, child_nr) 有一个自然的PK,您可以删除代理PK 列child_id。但我喜欢几乎每张桌子都有一个单列代理 PK ...
您可以使用触发器来限制数量,该触发器会在插入新孩子之前检查已经有多少孩子。但是你会遇到并发问题,而且它更昂贵、更不可靠、更容易规避并且是特定于供应商的。
如何管理child_nr?
RDBMS 只是强制(可靠地)表中永远不会存在非法状态。如何确定下一个 child_nr 取决于您。许多不同的方法都是可能的。
对于只有三个孩子,您可以在创建父母时自动插入所有孩子(使用触发器、规则或在您的应用程序中)。使用给定的 (parent_id, child_nr) 和其他列 NULL。
那么对于子表(GRANT/REVOKE),您将只允许UPDATE 而不允许INSERT 或DELETE,或者甚至确保使用另一个触发器,以便超级用户无法绕过它。使用ON DELETE CASCADE 将FK 设置为parent,这样孩子就会自动与父母一起死去。
另类
可靠性稍差,但更便宜:在parent 表中保留儿童数量并将其限制为<= 3。使用触发器更新 child 表中的每个更改。请务必涵盖更改子表中数据的所有可能方法。