外键 - 数据库设计

Posted

技术标签:

【中文标题】外键 - 数据库设计【英文标题】:Foreign keys - database design 【发布时间】:2017-03-06 09:38:40 【问题描述】:

在数据库设计期间,我发现了以下情况,我不确定我是否以正确的方式处理了它。所以有我的数据库架构:

此架构包含有关在给定服务器上运行的产品的数据。服务器可以在多个客户之间共享。表 ProductServer 告诉我们给定的产品已经安装在给定的服务器上。

由于产品/服务器的组合可以被多个客户使用(服务器可以有多个客户),我创建了另一个表实例,其中包含 ProductServer 行的附加信息。它包含有关哪个客户使用该产品及其优先级的信息。

我没有使用任何持久化框架,所以我手动编写了所有获取函数。

我的问题是:目前我有查询,连接所有表:

 SELECT * FROM ProductServer ps
 LEFT OUTER JOIN Product p ON ps.product_id = p.product_id
 LEFT OUTER JOIN Server s ON ps.server_id = s.server_id
 LEFT OUTER JOIN ServerCustomer sc ON s.server_id = sc.server_id
 **LEFT OUTER JOIN Customer c ON sc.customer_id = c.customer_id**
 LEFT OUTER JOIN Instance i ON ps.ps_id = i.ps_id
 **LEFT OUTER JOIN Customer c2 ON i.customer_id = c2.customer_id**

在我的 SQL 中,您可以看到标有 ** 的行,我必须在一个查询中将一张表连接两次,我不确定,但我觉得这可能是 db 的坏主意/坏设计。

我有一个想法将 ProductServer 和 Instance 拆分为一个表,但由于 ProductServer 表可能有 100k 行,我觉得最好将此表拆分为两个较小的表。

请您告诉我这是否设计不当,并转发给我可以弄清楚如何以更好的方式实现此问题的一些来源?

编辑: 我需要获取给定服务器的所有客户,因为我需要将所有数据获取到 Java 对象。这就是为什么我需要在一个数据库查询中将表 Customer 与 ServerCustomer 连接起来,并将 Customer 与 Instance 表连接起来。

【问题讨论】:

【参考方案1】:

您可能想要做的是重新安排您的加入,并且只加入到Customer 一次。不完全清楚您当前的条件是否应该由ANDOR 组合。我要和AND在这里:

SELECT * FROM ProductServer ps
 LEFT OUTER JOIN Product p ON ps.product_id = p.product_id
 LEFT OUTER JOIN Server s ON ps.server_id = s.server_id
 LEFT OUTER JOIN ServerCustomer sc ON s.server_id = sc.server_id
 LEFT OUTER JOIN Instance i ON ps.ps_id = i.ps_id
 LEFT OUTER JOIN Customer c ON sc.customer_id = c.customer_id
                            AND i.customer_id = c.customer_id

您可以这样做,因为联接不一定在两个表之间 - 它们位于表源之间,而这些表源本身可能已经是其他联接的结果。因此,在上面,当我们到达最后的ON 子句时,我们将左侧的ProductServer, Server, ServerCustomer, Instance 连接到右侧的Customer,并且我们可以引用这些表中的任何列作为连接的一部分条件。

【讨论】:

我进行这两个连接的原因是因为我使用此查询将所有这些数据提取到 Java 对象中。所以我需要在服务器对象中有所有客户对象,我还需要在实例对象中有客户对象。

以上是关于外键 - 数据库设计的主要内容,如果未能解决你的问题,请参考以下文章

数据库设计 - 多个外键

数据库中主键和外键的作用?

外键与数据库设计

将我的外键放在哪里以获得最佳数据库设计?

数据库设计:同一列用于 2 个不同的外键

使用外键的数据库设计 MySQL