我偶然发现了一个数据库设计,其中一个表在一列中包含需要连接的表的名称,在另一列中包含该表的外键(整数,而不是外键名称)。
我想知道你会如何解决这个问题?
这是目前的情况:
表聊天:
id | someColumn | chatter_id | chatter_ref
--------------------------------------------------------
1 2 1 customers
2 3 1 colleagues
3 4 2 customers
表客户:
id | colA
-------------
1 whatever
2 hello_world
表同事:
id | colB
-------------
1 yesyes
编辑:
我要做的是,有多个chatting
表,每个引用表一个。
像这样:
表chat_customers(使用customers表的外键):
id | someColumn | chatter_id
------------------------------------
1 2 1
3 4 2
表chat_colleagues(使用同事表的外键):
id | someColumn | chatter_id
------------------------------------
2 3 1
我会select case when chatter_ref = 'customers' then customers.colA else colleagues.colB end from ...
多个查询,而不是连接所有表并根据列chatter_ref(使用union
来决定从哪个表中选择)。这是要走的路吗?有没有更好的方法规范化这个?
答案 0 :(得分:2)
这是经典的Polymorphic Association反模式。有许多可能的解决方案:
1个专属弧(如Argeman所建议的),例如对于聊天桌
id | someColumn | customerId | colleagueId
------------------------------------------
1 2 1
2 3 1
3 4 2
其中customerId和colleagueID都可以为空,并且其中一个必须不为null。可以在customerId和colleagueId上声明外键。
2反转关系,例如从聊天表中删除chatterId和chatterRef并创建两个新表
客户聊天
chattingId | customerId
-----------------------
1 1
3 2
同事聊天
chattingId | colleagueId
------------------------
2 1
可以在customerId和colleagueId上声明外键。
3为客户/同事(如人员)创建超类型表,并让聊天表引用此新表的主键。
答案 1 :(得分:1)
我会在聊天表中放入两个或更多可空行,这些行引用不同的其他表。
例如,一列chatter_colleague和一个chatter_customer。这也不是很好,但我不知道任何真正的好解决方案!
这需要一些努力来保持桌面清洁,但据我所知,否则提供最佳的连接和索引功能。这很简单,这在我看来是可取的。
答案 2 :(得分:0)
将引用表的行合并为一个“表”并包含源表的名称(作为文字值),以便您可以将它们彼此区分开来,然后将主表连接到该表,同时加入id和源名称:
select
c.id,
c.someColumn,
d.data
from chatting c
left join (
select 'customers' type, id, colA data from customers
union all
select 'colleagues', id, colB from colleagues) d
on d.type = c.chatter_ref
and d.id = c.chatter_id