1。我的背景:
任何节点都有一个支撑......但这个支撑可以是墙或塔(实际上有大约7种不同类型的支撑)
重要:
type_support 列表示要处理哪个表(墙壁或塔架)。您可以将其视为“参数化多态性”的参数。
id_wall 从 0 开始到 n 堵墙。
id_pylon 从 0 开始直到 n 个塔。
2。数据库结构
+-------------+
| wall |
+-------------+ PK +-------------+
| node | |--------|id_wall | Legend:
+-------------+ | +-------------+ PK means Primary key
|id_node | | FK means Foreign key
|type_support | FK | +-------------+
|id_support |------| | Pylon |
+-------------+ | PK +-------------+
|--------|id_pylon |
+-------------+
3.代码(星号(*)之间的代码是幼稚/愚蠢的)
CREATE TABLE node (
id_node INTEGER NOT NULL PRIMARY KEY,
type_support INTEGER NOT NULL,
id_support INTEGER NOT NULL,
FOREIGN KEY (id_support) REFERENCES *The_right_support_table(id_the_right_support)*;
如何做到这一点?
编辑:目前我使用 SQLite,稍后它将是 PostgreSQL)
您有多种选择。
你可以做你已经做过的事情,有一个ID列和一个类型列。这就是 Rails 实现多态性的方式。
缺点是缺乏引用完整性。您可以使用触发器强制执行此操作,而不是使用外键。
另一个缺点是公共支持数据必须在所有支持表中重复。例如,支撑可能都有一个“高度”,因此每个“支撑”表都必须有一个高度列。查询这些公共属性变得很困难。你可以用风景来弥补这一点。
create view node_support as
select
node.id,
support_id,
support_type,
case when pylon.id is not null then pylon.height
when wall.id is not null then wall.height
end as height,
case when pylon.id is not null then pylon.max_load
when wall.id is not null then wall.max_load
end as max_load
from node
left join wall on node.support_type = 'wall' and wall.id = node.support_id
left join pylon on node.support_type = 'pylon' and pylon.id = node.support_id
示范.
如果你的数据库支持,你可以使用表继承。
create table support (
id serial primary key,
height integer,
max_load integer
);
create table wall (
color text
) inherits(support);
create table pylon (
shape text
) inherits(support);
create table node (
-- Referential integrity must be handled with a trigger.
support_id integer not null
);
您可以轻松查询所有支撑,或仅查询墙壁,或仅查询塔架。
表继承有一些注意事项,并且它是 Postgres 特定的。
最大的警告是,如果您尝试
support_id integer references support(id)
,这不适用于墙壁或塔架。因此,您又回到通过触发器强制引用完整性。
示范.
您可以为每种类型的支持创建一个连接表。
create table node_wall (
node_id integer not null references node(id),
wall_id integer not null references wall(id)
);
create table node_pylon (
node_id integer not null references node(id),
pylon_id integer not null references pylon(id)
);
缺点是...
您可以创建一个视图来查询节点及其支持度。
create view node_support as
select
node.id,
coalesce(pylon_id, wall_id) as support_id,
case when pylon_id is not null then 'pylon'
when wall_id is not null then 'wall'
end as type
from node
left join node_wall on node_wall.node_id = node.id
left join node_pylon on node_pylon.node_id = node.id
示范.
您可以拥有一张
support
桌子,然后是专门的桌子。
create table support (
id integer primary key
-- columns related to any support
);
create table wall (
id integer primary key,
support_id integer not null references support(id)
-- columns only related to walls
);
create table pylon (
id integer primary key,
support_id integer not null references support(id)
-- columns only related to pylons
);
现在
node
可以参考support
。查询通用支持信息很容易。
缺点是: