没有唯一数据的表的PK

时间:2014-06-19 18:26:46

标签: sql database database-design database-performance

我有两张表,比如

Company( #id_company, ... )

addresses( address, *id_company*, *id_city* )

cities( #id_city, name_city, *id_county* )

countries( #id_country, name_country )

我想要的是:

这是一个很好的设计? (公司可以有很多地址)

重要的是,我注意到我没有为PK表添加addresses因为公司的每个地址都不同,我是对的吗?

我将永远不会在where中指定一个地址{/ 1}}。

5 个答案:

答案 0 :(得分:1)

没关系 - 您可能想在company_id上添加一些非唯一索引,以便加快公司地址查询。另一个选择是在公司和地址之间建立一个连接表,但如果地址存储了更多数据(因此搜索速度较慢),这可能只是合理的。

答案 1 :(得分:1)

这个设计很好。

(关系)表始终具有(候选)键。 (其中一个可以选择作为主键,但是候选键,也就是键,是重要的。)因为如果没有小于所有列的列的列的子集是唯一的,那么键是所有列的集合。

由于每个表都有一个,因此在SQL中你应该声明它。例如,在SQL中,如果要为此表的键声明FOREIGN KEY约束,则必须声明该列通过PRIMARY KEY,KEY或UNIQUE设置键。另外,告诉DBMS您了解的内容有助于优化您的使用。

确定键的重要性是列的子集,这些列是唯一的,没有较小的唯一子集。这些是关键。

A company, address or city is not unique since you are going to have multiple of each.
A (city,address) is not unique normally.
A (city,company) is not unique normally.
A (company,address) is not unique normally.
So (company,address,city) is the (only) (candidate) key.

请注意,如果只有一个城市,那么(公司,地址)就是关键。如果只有一家公司,那么(地址,城市)将成为关键。所以你的理由是“因为公司[?]的每个地址[+城市?]会有所不同”,除非我们假设其他事情,否则不合理。

答案 2 :(得分:1)

首先,我们应该区分自然键和技术键。至于自然键:

  1. 一个国家的名称唯一标识。
  2. 城市可以通过其国家/地区和唯一名称进行唯一标识。例如,德国有两个法兰克福。为了确定我们所谈论的内容,我们要么使用不同的名称Frankfurt / Main和Frankfurt / Oder,要么使用城市名称及其邮政编码范围。
  3. 公司通常以其全名识别。或者使用一些税号,代码等等。
  4. 要唯一标识公司地址,我们会将公司地址加上城市中的国家,城市和地址(通常是街道名称和地址)。
  5. 您决定使用技术密钥。没关系。但是你仍然应该确保名称是唯一的。你不希望法国和法国在你的桌子上,它必须只在那里一次。你不希望法兰克福和法兰克福在你的德国城市表中没有任何区别。并且您不希望为一家公司输入两次相同的地址。

    • 公司(#id_company,name_company,...)加上name_country上的唯一约束或任何使公司成为唯一的
    • 国家/地区(#id_country,name_country)以及name_country上的唯一约束
    • cities(#id_city,name_city, id_county )加上name_city的唯一约束,id_country
    • 地址(地址, id_company id_city ),所有三列都有唯一约束

    根据您的说法,您似乎只想要查找地址。您不希望在任何其他表中使用它们,现在而不是将来。那么,你完成了。由于您需要对所有三列都有唯一约束,您也可以将其声明为主键,但您不必这样做。

    请记住,要在任何其他未来的表中引用公司地址,您必须在该表中存储地址+ id_company + id_city。那时你肯定想要一个地址id。但您可以在需要时添加。现在你可以不用了。

答案 3 :(得分:1)

由于篇幅原因,我将此作为答案而不是评论。对于具有定义的主键的地址表,答案是肯定的。有几个很好的理由,但只考虑一下。

假设公司有多个地址,并且移动要求您删除其中一个地址。您不能删除where comp_id = x,因为这会删除该公司的所有地址。您必须拥有where comp_id = x and something_else 其他必须将该地址与该公司的所有其他地址区分开来。因此,您必须让某人查看不同的地址以查看它们之间的区别,并选择正确标识一个地址的一个区别,然后将其正确写入where子句。

每次要删除(或更新)地址时,都要做很多工作。

这也意味着编写可用于删除任何地址的参数化删除语句会更加困难。假设一家公司在同一栋楼内有多个地点:套房101运输,套房202营销和地下室(当然)IT。所以街道,城市,州,一切都是一样的,只有Suite_No或用于改进地址的任何东西都不同。

然后考虑您的用户。大多数情况下,用户不会有兴趣查看您为公司列出的每个地址。他只对产品测试感兴趣。您应该能够为他们提供产品测试的地址,而不是其他。用户在每次进行查询时都会出现数据转储,并且不会因为耐心而闻名,而且他们可以选择他们正在寻找的数据转储。

它只是解决了很多问题,无法指定where addr_id = x

答案 4 :(得分:1)

地址是一个东西,应该有自己的表。

地址可以在没有公司的情况下存在,因此它不应该有公司的外键。另外,如果你开始向个人出售/购买会怎么样?

公司可以拥有零个,一个或多个地址。

两个或更多公司可以拥有完全相同的地址。你的假设是有缺陷的。

使用联结表:

company -< company_address >- address