问题描述
有区域、头像和区域实例。每个区域的头像必须属于零个或一个实例。
CREATE TABLE zones (
id SERIAL NOT NULL PRIMARY KEY,name VARCHAR NOT NULL,...
);
CREATE TABLE avatars (
id SERIAL NOT NULL PRIMARY KEY,...
);
CREATE TABLE instances (
id SERIAL NOT NULL PRIMARY KEY,zone_id INTEGER REFERENCES zones NOT NULL,...
);
CREATE TABLE avatar_instances (
avatar_id INTEGER REFERENCES avatars NOT NULL,instance_id INTEGER REFERENCES instances NOT NULL,PRIMARY KEY(avatar_id,zone_id)
);
我对上面的架构不满意,因为 zone_id
中每条记录中的 avatar_instances
必须与相应 zone_id
行内的 instances
一致。
理想情况下,我希望在 avatar_instances 上有一个唯一索引,它“到达”instances
表的内部以查看 instances.zone_id
。
例如
CREATE TABLE avatar_instances (
avatar_id INTEGER REFERENCES avatars NOT NULL,instance.zone_id)
);
如何将此模式转换为第 N 个范式,同时保留“每个头像必须属于每个区域的零个或一个实例”的限制?
解决方法
创建一个唯一值并添加一个复合 FK 引用唯一值。
CREATE TABLE instances (
id SERIAL NOT NULL PRIMARY KEY,zone_id INTEGER REFERENCES zones NOT NULL,UNIQUE (zone_id,id)
);
CREATE TABLE avatar_instances (
avatar_id INTEGER REFERENCES avatars NOT NULL,zone_id INTEGER NOT NULL,instance_id INTEGER NOT NULL,CONSTRAINT fk_ai2i FOREIGN KEY (zone_id,instance_id) REFERENCES instances (zone_id,id),PRIMARY KEY(avatar_id,zone_id)
);
如果 Avatar 必须属于每个区域的零个或一个实例,则在 avatar_instances.instance_id
中允许为 null。