8

这是一个 SQL 设计问题。首先,设置。我有三张桌子:

  1. A,根据对链接服务器的查询自动填充。此表中的数据不能更改;
  2. B,只有十几行,包含 As 集合的名称;
  3. AtoB,这是将 As 组织成命名集合的映射表,两列都有外键;

SQL 映射表

例如,A 包含:

  1. 长颈鹿
  2. 猫头鹰
  3. 老虎

B 包含:

  1. 西雅图动物园
  2. 圣何塞动物园

AtoB 包含:

1,1(西雅图的长颈鹿)
2,1(西雅图的猫头鹰)
3,1(西雅图的老虎)
2,2​​(圣何塞的猫头鹰)

现在,问题:

我被要求在其中一些集合中包含 A 中没有的项目。因此,我创建了一个表 C,它具有与 A 相同的标识和名称列,并填充它。与前面的示例保持一致,假设 C 包含:

问题是,如何在 AtoB 中包含来自 C 的项目?如果我需要在西雅图动物园里放一条龙怎么办?

天真的我的第一直觉是创建一个包含 A 和 C 联合的视图 V,并将 AtoB 修改为 VtoB。这就是我的天真得到回报的地方:无法为视图创建外键。

我怀疑有一种标准的、正确的方法可以将一个或多个 A 或 C 与 B 联系起来。

4

4 回答 4

13

要扩展 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"
于 2010-01-11T21:18:25.633 回答
5

如果您不能在 A 中放置 Dragon,那么您将需要创建另一个表和另一个链接表。问题是创建一组需要存储的唯一数据(另一个表),不能与 A 相同。由于它不是同一组,因此您不能再使用具有外部的链接表(AtoB)确保链接是来自集合 A 的引用的键。因此您可以创建如下表:

虚构的生物

  • ID
  • 姓名

imaginary_creatures_to_b

  • imaginary_creatures_id(链接到 imaginary_creatures 表)
  • b_id(链接到 zoos 表)

稍后当您想获得动物园中的所有生物时,您可以执行 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'))

可能有更好的写法,但它应该适合您的目的。

于 2010-01-11T21:02:36.260 回答
1

Arthur Thomas 有一个很好的解决方案,另一个可能的解决方案是在链接表中添加一列,指示它与哪个表(A 或 C)相关。然后通过触发器而不是外键强制关系。但实际上亚瑟的解决方案是做这类事情的首选方式。

于 2010-01-11T21:08:20.503 回答
0

您要做的是将Dragon放入A中,如果您想从A中选择所有记录,而不管它们在AtoB中是否有匹配的记录,请执行LEFT OUTER JOIN。像这样的东西:

SELECT * FROM A
LEFT OUTER JOIN AtoB
ON A.id = AtoB.A_ID

编辑:这只有在您可以将新记录添加到 A 时才有效。我错过了您无法添加的事实。我认为亚瑟托马斯的解决方案就是你想要的。

于 2010-01-11T20:43:46.857 回答