2

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

问题是,根据诸如此类的许多来源,每个表都应该有一个主键吗?您应该在数据库的每个表中都有一个主键。

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

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

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

4

6 回答 6

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)
于 2012-09-01T00:36:54.153 回答
2

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

于 2012-09-01T00:46:45.530 回答
2

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

这个复合键是否也是主键,或者您将拥有另一个键(将充当代理主键)是另一回事,但无论哪种方式,您都需要这个复合键。

请注意,在支持集群的数据库(又名索引组织表)下,PK 通常也是一个集群键,这可能会对性能产生重大影响。


1与 mutiset 不同。

于 2012-09-01T03:42:56.693 回答
2

具有重复行的表不能充分表示关系。这是一袋行,而不是一组行。如果你让这种情况发生,你最终会发现你的计数将被取消,你的总和将被取消,你的平均值将被取消。简而言之,当你去使用它时,你会从你的数据中得到令人困惑的错误。

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

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

现实世界中的实体与该实体的表中相应行之间的一一对应关系超出了 DBMS 的范围。由您的应用程序甚至您的数据提供者通过不为现有实体发明新行并且不让一些新实体从裂缝中溜走来维持这种对应关系。

于 2012-09-01T12:52:31.547 回答
1

好吧,既然您在问,这是一种很好的做法,但在少数情况下(不需要连接数据),它可能不是绝对需要的。但最大的问题是你永远不知道需求是否会改变,所以你现在真的想要一个,所以你不会在事后向 10m 记录表添加一个......

除了主键(顺便说一句,它可以跨越多个列)之外,我认为拥有一个作为单个字段的辅助候选键是一种很好的做法。这使得连接更容易。

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

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

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

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

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

需要候选键的一个例外可能是确实可能出现重复记录。例如,假设我们正在跟踪发票。我们可能会遇到这样一种情况,即有人为两个项目单独开具发票,两个项目中的每一个都显示一个。这些可能是相同的。在这种情况下,您可能想要添加一个人工主键,因为它允许您稍后将事物加入该记录。您现在可能不需要这样做,但将来可能!

于 2012-09-02T10:27:57.217 回答
0

创建复合主键。要详细了解复合主键是什么,请访问 http://www.relationaldbdesign.com/relational-database-analysis/module2/concatenated-primary-keys.php

于 2013-06-02T04:24:27.353 回答