133

我有两张桌子:

  • 用户(用户名、密码)
  • 个人资料(profileId,性别,出生日期,...)

目前我正在使用这种方法:每个配置文件记录都有一个名为“userId”的字段作为链接到用户表的外键。当用户注册时,他的个人资料记录会自动创建。

我对朋友的建议感到困惑:将“userId”字段作为键和键并删除“profileId”字段。哪种方法更好?

4

9 回答 9

172

外键几乎总是“允许重复”,这会使它们不适合作为主键。

相反,找到一个唯一标识表中每条记录的字段,或添加一个新字段(自动递增整数或 GUID)作为主键。

唯一的例外是具有一对一关系的表,其中链接表的键和键是相同的。

于 2012-06-11T15:21:14.103 回答
56

主键总是需要唯一,如果表是一对多关系,外键需要允许非唯一值。如果表是通过一对一关系而不是一对多关系连接的,则使用外键作为主键是完全可以的。如果您希望同一用户记录有可能拥有超过 1 条相关的个人资料记录,请使用单独的主键,否则坚持您拥有的。

于 2012-06-11T15:26:22.307 回答
21

是的,主键是外键是合法的。这是一个罕见的结构,但它适用于:

  • 1:1 的关系。这两个表不能合并为一个,因为不同的权限和特权仅适用于表级别(截至 2017 年,这样的数据库会很奇怪)。

  • 1:0..1 的关系。配置文件可能存在也可能不存在,具体取决于用户类型。

  • 性能是一个问题,并且设计充当分区:与用户表相比,配置文件表很少被访问,托管在单独的磁盘上或具有不同的分片策略。如果下划线存储是柱状的,则没有意义。

于 2017-11-29T23:09:52.590 回答
8

是的,在这些表之间存在一对一关系的情况下,外键可以是主键

于 2017-10-03T02:58:47.570 回答
3

建立一对一的关系通常被认为是不好的做法。这是因为您可以只将数据表示在一个表中并获得相同的结果。

但是,在某些情况下,您可能无法对所引用的表进行这些更改。在这种情况下,使用外键作为主键没有问题。拥有一个由自动递增的唯一主键和外键组成的复合键可能会有所帮助。

我目前正在开发一个用户可以登录并生成注册码以与应用程序一起使用的系统。由于我不会进入的原因,我无法简单地将所需的列添加到用户表中。因此,我将使用代码表进行一对一的路由。

于 2016-03-22T17:04:49.803 回答
2

我不会那样做。我会保留profileID表的主键Profile

外键只是两个表之间的引用约束

有人可能会争辩说,作为从其他表中引用它的任何外键的目标,主键是必要的。外键是任何表中的一个或多个列的集合(不一定是该表的候选键,更不用说该表的主键),它可以保存在某些表的主键列中找到的值其他表。所以我们必须有一个主键来匹配外键。还是我们必须?主键/外键对中的主键的唯一目的是提供一个明确的连接 - 以保持对包含被引用主键的“外”表的引用完整性。这确保外键引用的值始终有效(如果允许,则为 null)。

http://www.aisintl.com/case/primary_and_foreign_key.html

于 2012-06-11T15:21:04.747 回答
1

这取决于业务和系统。

如果您的 userId 是唯一的并且始终是唯一的,您可以使用 userId 作为您的主键。但是,如果你想扩展你的系统,那会让事情变得很困难。我建议您在表用户中添加外键以与表配置文件建立关系,而不是在表配置文件中添加外键。

于 2012-06-12T03:51:29.997 回答
0

它并不完全适用于问题的情况,但由于我最终在这个问题上搜索其他信息并阅读了一些评论,我可以说在表中只有一个 FK 并获得唯一值是可能的。您可以使用具有只能分配 1 次的类的列,它的工作方式几乎与 ID 类似,但是如果您想使用唯一的分类值来区分每条记录,则可以这样做。

于 2021-07-22T18:59:07.307 回答
0

简短回答:取决于....在这种特殊情况下,它可能没问题。但是,专家几乎每次都会反对它。包括你的情况。

为什么?

表中的键很少是唯一的,因为它们对于所讨论的表来说是外来的(起源于另一个表中)。例如,项目 ID 在 ITEMS 表中可能是唯一的,但在 ORDERS 表中可能是唯一的,因为同一类型的项目很可能存在于另一个订单中。同样,订单 ID 在 ORDERS 表中可能是唯一的(可能),但在诸如 ORDER_DETAILS 之类的其他表中不是唯一的,其中可以存在具有多个行项目的订单并查询特定订单中的特定项目,您需要连接两个FK(order_id 和 item_id)作为此表的 PK。

我不是数据库专家,但如果你能从逻辑上证明有一个自动生成的值作为你的 PK,我会这样做。如果这不切实际,那么两个(或更多)FK 的串联可以作为您的 PK。但是,我想不出任何可以将单个 FK 值证明为 PK 的情况。

于 2019-05-16T18:54:01.797 回答