为什么我的数据库表需要主键?

时间:2012-09-01 00:33:50

标签: database database-design entity-relationship

在我的数据库中,我有一个用户列表,其中包含有关它们的信息,我还有一个功能,允许用户将其他用户添加到候选名单中。我的用户信息存储在一个表中,其中包含用户ID的主键,我有另一个用于候选名单的表。短名单表的设计使它有两列,基本上只是一对名称列表。因此,要查找特定用户的候选名单,请从第二列中检索所有名称,其中第一列中的id是特定值。

问题在于,根据许多来源,例如此Should each and every table have a primary key?,您应该在数据库的每个表中都有一个主键。

根据此源http://www.w3schools.com/sql/sql_primarykey.asp - 唯一标识数据库中条目的主键。所以我的问题是:

  1. 我的数据库中的表有什么问题?为什么需要主键?

  2. 我应该如何给它一个主键?只需创建一个新的自动递增列,以便每个条目都有唯一的ID?这似乎没有多大意义。或者我会以某种方式将表示候选名单的多个条目封装到另一个表中的另一个实体中并将其链接到?我真的很困惑。

6 个答案:

答案 0 :(得分:2)

如果行是唯一的,则可以使用双列主键,尽管可能与数据库有关。这是一个例子:

CREATE TABLE my_table
(
col_1 int NOT NULL,
col_2 varchar(255) NOT NULL,
CONSTRAINT pk_cols12 PRIMARY KEY (col_1,col_2)
)

如果您已经拥有该表,则示例为:

ALTER TABLE my_table
ADD CONSTRAINT pk_cols12 PRIMARY KEY (col_1,col_2)

答案 1 :(得分:2)

主键必须唯一地标识每条记录,并且如前所述,主键可以包含多个属性(1个或多个列)。首先,我建议确保每张记录在您的表格中都是独一无二的。其次,根据我的理解,你离开了没有主键的表,并且不允许这样做,你需要为它设置密钥。

答案 2 :(得分:2)

在这种特殊情况下,同一对用户ID中没有任何目的在shortlist表中存储多次。毕竟,该表为一个集合建模,一个元素在集合中或不在集合中。在集合中具有“两次”元素没有意义 1 。为防止这种情况,请创建一个由这两个用户ID字段组成的复合键。

这个复合键是否也是主键,或者你将另一个键(它将作为代理主键)是another matter,但无论哪种方式,你都需要这个复合键。

请注意,在支持clustering (aka. index-organized tables)的数据库中,PK通常也是群集密钥,这可能会对性能产生重大影响。


1 与mutiset不同。

答案 3 :(得分:2)

具有重复行的表不足以表示关系。它是一包行,而不是一组行。如果你发生这种情况,你最终会发现你的计数将被取消,你的金额将被取消,你的平均数将会被取消。简而言之,当您使用它时,您的数据会出现令人困惑的错误。

声明主键是防止重复行进入数据库的便捷方法,即使其中一个应用程序出错也是如此。您获得的索引是副作用。

可以通过引用任何候选键来对表中的单个行进行外键引用。但是,如果将其中一个候选键声明为主键,然后使所有外键引用引用主键,则会更方便。这只是谨慎的数据管理。

现实世界中的实体与该实体的表中的相应行之间的一对一对应关系超出了DBMS的范围。这取决于您的应用程序甚至您的数据提供者通过不为现有实体发明新行而不让一些新实体漏掉这些内容来维护该通信。

答案 4 :(得分:1)

好吧,因为你问,这是一个很好的做法,但在少数情况下(数据不需要连接),可能不是绝对必需的。但最大的问题是你从来没有真正知道需求是否会发生变化,所以你现在真的想要一个,所以你不会在事实之后添加一个10米的记录表......

除了主键(可以跨越多列btw)之外,我认为最好有一个辅助候选键,它是一个单独的字段。这使得连接更容易。

首先是一些理论。您可能还记得HS或大学代数中函数的定义是y = f(x)其中f是函数,当且仅当每个x只有一个y时。在这种情况下,在关系数学中,我们会说在这种情况下y在{x}上是functionally dependent

您的数据也是如此。假设我们存储支票号码,检查帐号和金额。假设我们可能有多个支票账户,并且对于每个支票账户,不允许重复的支票号码,那么金额在功能上取决于(账户,支票号码)。通常,您希望将数据存储在一起,这些数据在功能上依赖于同一事物,没有传递依赖性。主键通常是您指定为主键的功能依赖项。然后,这将标识行中的其余数据(因为它与该标识符绑定)。可以将其视为natural primary key.尽可能(即不使用MySQL)我喜欢将主键声明为自然键,即使它跨越列。有时您可能有多个可互换的候选键,这会很复杂。例如,考虑:

CREATE TABLE country (
    id serial not null unique,
    name text primary key,
    short_name text not null unique
);

这个表确实可以将任何列作为主键。这三个都是完全可以接受的候选键。假设我们有一个国家记录(232,'美国','美国')。这些字段中的每一个都唯一地标识记录,因此如果我们知道一个记录,我们就能知道其每一个都可以定义为主键。

我还建议使用第二个人工候选键,它只是用于链接连接的机器标识符。在上面的示例中,country.id执行此操作。这对于将其他记录链接到国家/地区表非常有用。

需要候选键的例外情况可能是重复记录确实存在的地方。例如,假设我们正在跟踪发票。我们可能会遇到一个案例,即某人独立开具两个项目的发票,其中一个项目显示在两个项目的每一个上。这些可能是相同的。在这种情况下,您可能希望添加一个人工主键,因为它允许您稍后将事物连接到该记录。您现在可能没有必要这样做,但将来可能会这样做!

答案 5 :(得分:0)

创建复合主键。 要阅读有关复合主键的更多信息,请访问 http://www.relationaldbdesign.com/relational-database-analysis/module2/concatenated-primary-keys.php