多表之间的SQL映射

发布于 2024-08-17 11:13:05 字数 763 浏览 9 评论 0原文

这是一个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 包含:

  1. Dragon

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

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

我怀疑存在一种标准、正确的方法将一个或多个 A 或 C 与 B 相关联。

This is a SQL design question. First, the setup. I have three tables:

  1. A, which is automatically populated based on a query against a linked server. The data in this table cannot be changed;
  2. B, which has just a dozen or so rows, containing the names for collections of As;
  3. AtoB, which is the mapping table by which As are organized into named collections, with foreign keys on both columns;

SQL Mapping Table

For example, A contains:

  1. Giraffe
  2. Owl
  3. Tiger

And B contains:

  1. Seattle Zoo
  2. San Jose Zoo

And AtoB contains:

1,1 (Giraffe in Seattle)
2,1 (Owl in Seattle)
3,1 (Tiger in Seattle)
2,2 (Owl in San Jose)

Now, the problem:

I've been asked to include in some of these collections items not found in A. So, I create a table, C, with the same identity and Name columns as A, and populate it. In keeping with the earlier example, let's say C contains:

  1. Dragon

The question is, how do I include items from C in AtoB? What if I need to include a Dragon in the Seattle Zoo?

My first instinct, being naive, was to create a view V containing the union of A and C, and modifying AtoB to be VtoB. That's where my naivety paid off: one cannot create a foreign key to a view.

I suspect that there's a standard, correct means of relating one or more A OR C with a B.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦年海沫深 2024-08-24 11:13:05

为了扩展 Arthur Thomas 的解决方案,这里有一个在子选择中没有 WHERE 的 union ,以便您可以创建通用视图:

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"

To expand on Arthur Thomas's solution here's a union without the WHERE in the subselects so that you can create a universal view:

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

Then, you can perform a query like:

SELECT Animal FROM zoo_animals WHERE Zoo="Seattle Zoo"
樱娆 2024-08-24 11:13:05

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

imaginary_creatures

  • id
  • name

imaginary_creatures_to_b

  • imaginary_creatures_id (链接到 imaginary_creatures 表)
  • b_id (链接到动物园表)

稍后,当您想要获取 a 中的所有生物时动物园你可以做一个联盟

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'))

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

If you can't put a Dragon in A then you will need to create another table and another link table. The problem is creating a unique set of data that needs to be stored (another table) that cannot be the same set as A. Since it isn't the same set then you can no longer use the link table (AtoB) which has foreign keys that ensure that the link is a reference from set A. So you could create a tables like this:

imaginary_creatures

  • id
  • name

imaginary_creatures_to_b

  • imaginary_creatures_id (link to imaginary_creatures table)
  • b_id (link to zoos table)

Later when you want to get all creatures in a zoo you can do 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'))

There may be a better way of writing that, but it should work for your purposes.

谜兔 2024-08-24 11:13:05

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

Arthur Thomas has a good solution, the other possible solution is to add a column to the link table indicating which table (A or C) it is related to. Then enforce the relationships through triggers rather than foreign keys. But really Arthur's solution is the preferred way of doing this sort of thing.

离线来电— 2024-08-24 11:13:05

你想要做的是将 Dragon 放入 A 中,如果你想选择 A 中的所有记录,无论它们在 AtoB 中是否有匹配的记录,请执行 LEFT OUTER JOIN。像这样的事情:

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

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

What you want to do is put Dragon in A, and if you want to select ALL records from A regardless of if they have a matching record in AtoB, do a LEFT OUTER JOIN. Something like this:

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

Edit: This would only work if you could add your new records to A. I missed the fact that you are not able to. I think Arthur Thomas's solution is what you want.

阿楠 2024-08-24 11:13:05
  1. 截断表 dept_details
  2. 显示表 emp_details 的结构
  3. 将 emp_name 的第一个字母转换为大写。
  1. Truncate the table dept_details
  2. Display the structure of the table emp_details
  3. Convert the first letter of emp_name into capitals.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文