转化为范式

问题描述

有区域、头像和区域实例。每个区域的头像必须属于零个或一个实例。

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。