这是一个SQL设计问题。首先,设置。我有三张桌子:
例如,A包含:
B包含:
AtoB包含:
1,1(西雅图的长颈鹿)
2,1(西雅图猫头鹰)
3,1(西雅图老虎)
2,2(圣何塞的猫头鹰)
现在,问题是:
我被要求在A中包含一些在A中找不到的项目。因此,我创建了一个表C,其中包含与A相同的标识和名称列,并填充它。与前面的例子一致,假设C包含:
问题是,如何在AtoB中包含C中的项目?如果我需要在西雅图动物园中加入一条龙怎么办?
我的第一直觉是天真,就是创建一个包含A和C联合的视图V,并将AtoB修改为VtoB。这就是我的天真得到回报的地方:一个人无法为视图创建外键。
我怀疑有一种标准的,正确的方法可以将一个或多个A OR C与B联系起来。
答案 0 :(得分:10)
要扩展Arthur Thomas的解决方案,这里是一个union
,在子选择中没有WHERE,以便您可以创建一个通用视图:
SELECT A.Name as Animal, B.Name as Zoo FROM A, AtoB, B
WHERE AtoB.A_ID = A.ID && B.ID = AtoB.B_ID
UNION
SELECT C.Name as Animal, B.Name as Zoo FROM C, CtoB, B
WHERE CtoB.C_ID = C.ID && B.ID = CtoB.B_ID
然后,您可以执行以下查询:
SELECT Animal FROM zoo_animals WHERE Zoo="Seattle Zoo"
答案 1 :(得分:5)
如果你不能将龙放入A,那么你需要创建另一个表和另一个链表。问题是创建一个需要存储的唯一数据集(另一个表),它不能与A设置相同。因为它不是同一个集,所以你不能再使用具有外来的链接表(AtoB)确保链接是来自集合A的引用的键。因此,您可以创建如下表格:
后来当你想要动物园中的所有生物时,你可以做一个UNION
SELECT A.Name FROM A where A.ID IN
(SELECT AB.A_ID FROM AtoB AB WHERE B_ID =
(SELECT B.ID FROM B WHERE B.Name = 'Zoo Name'))
UNION
SELECT i.name FROM imaginary_creatures i i.id IN
(SELECT ic.imaginary_creatures_id FROM imaginary_creatures_to_c ic
WHERE ic.b_id = (SELECT B.ID FROM B WHERE B.Name = 'Zoo Name'))
可能有更好的写作方式,但它应该适用于您的目的。
答案 2 :(得分:1)
Arthur Thomas有一个很好的解决方案,另一个可能的解决方案是在链接表中添加一个列,指示它与哪个表(A或C)相关。然后通过触发器而不是外键强制执行关系。但是Arthur的解决方案确实是做这种事情的首选方式。
答案 3 :(得分:0)
你想要做的是将龙放在A中,如果你想从A中选择所有记录而不管他们是否在AtoB中有匹配的记录,那么做一个LEFT OUTER JOIN。像这样:
SELECT * FROM A
LEFT OUTER JOIN AtoB
ON A.id = AtoB.A_ID
编辑:这只有在您可以将新记录添加到A时才有效。我错过了您无法做到的事实。我认为Arthur Thomas的解决方案就是你想要的。