我有这个七表数据库存储具有历史价值的区域(例如旧墓地或石器时代的房屋遗址),可以划分为子区域。对这些地区进行了检查和挖掘。区域、子区域、检查和挖掘这四个表都可以有一个或多个“位置”或“发现”。
位置表和查找表目前与链接表相关,链接表包含目标表的名称和该表中的目标 ID,例如target_table="subarea", target_id=5
.
问题是在数据库中存储表名是我的理解不是好的做法。那么,将位置和查找与四个表中的任何一个的 N-1 关系联系起来的最佳解决方案是什么?
我有这个七表数据库存储具有历史价值的区域(例如旧墓地或石器时代的房屋遗址),可以划分为子区域。对这些地区进行了检查和挖掘。区域、子区域、检查和挖掘这四个表都可以有一个或多个“位置”或“发现”。
位置表和查找表目前与链接表相关,链接表包含目标表的名称和该表中的目标 ID,例如target_table="subarea", target_id=5
.
问题是在数据库中存储表名是我的理解不是好的做法。那么,将位置和查找与四个表中的任何一个的 N-1 关系联系起来的最佳解决方案是什么?
有很多不同的方法可以做到这一点。我的解决方案使用了 PostgreSQL 的一些有争议的特性,因此请参阅下面的注意事项。
CREATE TABLE link_categories (
id int not null unique,
label text primary key
);
INSERT INTO link_categories(id, label)
VALUES (1, 'Area'),
(2, 'Sub-area'),
(3, 'Inspection'),
(4, 'Excavation');
CREATE TABLE location_base (
-- add your base fields here
link_category int not null,
refkey bigint not null -- assume all id's on the other tables are bigints?
);
CREATE TABLE finding_base (
-- add your base fields here
link_category int not null,
refkey bigint not null -- see above
);
然后我会使用表继承来创建子表,以管理您的多态关联。
CREATE TABLE location_area (
CHECK (link_category = 1),
FOREIGN KEY (refkey) REFERENCES area(id),
PRIMARY KEY (...) -- needs to be repeated for each child table
) INHERITS (location_base);
CREATE TABLE location_subarea (
CHECK (link_category = 2),
FOREIGN KEY (refkey) REFERENCES subarea(id),
PRIMARY KEY (...) -- needs to be repeated for each child table
) INHERITS (location_base);
等对结果表重复
请注意,表继承在 PostgreSQL 上是一个颇有争议的特性。您需要考虑利用表继承的一些底层怪癖来发挥您的优势,并像表分区系统一样实现它。请注意,在这种情况下,link_category 基本上成为主键的一部分。
但是,在使用此解决方案之前,请阅读 PostgreSQL 文档:
请注意,这是一个有点危险的特性,但多态关联通常会带来危险。我在这里特别推荐这个,因为我认为它可以简化你的失败案例,即使它是以牺牲其他一些东西为代价的。