5

在代表一个人(如客户、用户、客户、员工等)的表中,您对主键的选择是什么?我的第一选择是社会安全号码 (SSN)。但是,由于隐私问题和不同的法规,不鼓励使用 SSN。SSN 可以在人的一生中改变,所以这是反对它的另一个原因。

我想精心选择的自然主键的功能之一是避免重复。我不希望一个人在数据库中注册两次。一些代理或生成的主键无助于避免重复条目。解决这个问题的最佳方法是什么?

在您的应用程序中保证人员实体唯一性的最佳方法是什么?这可以在数据库级别使用主键或唯一性约束来处理吗?

4

8 回答 8

7

我不知道您使用的是哪个数据库引擎,但是(至少对于 MySQL - 请参阅7.4.1。使您的数据尽可能小,使用尽可能短的整数通常被认为是性能和内存的最佳选择要求。

我会使用一个整数 ,auto_increment作为该主键。
这个想法是:

  • 如果 PK 很短,它有助于识别每一行(比较两个整数比比较两个长字符串更快、更容易)
  • 如果外键中使用的列很短,则外键需要更少的内存,因为该列的值可能存储在多个位置。

然后,如果可能和/或必要的话,在另一列上设置UNIQUE索引——确定唯一性的那一列。


编辑:以下是您可能感兴趣的其他几个问题/答案:

于 2009-12-24T12:44:02.873 回答
3

如上所述,使用自动增量作为主键。但我不相信这是你真正的问题。

您真正的问题是如何避免重复条目。从理论上讲,这是不可能的——两个人可能在同一天出生,同名,住在同一个家庭,而其中一个人没有社会保险号。(一个可能是访问该国的外国人)。

但是,全名、生日、地址和电话号码的组合通常足以避免重复。请注意,输入的地址可能不同,人们可能有多个电话号码,人们可能会选择省略中间名或使用首字母。这取决于避免重复条目的重要性,以及您的用户群有多大(以及因此发生冲突的可能性)。

当然,如果您可以获得 SSN/SIN,则使用它来确定唯一性。

于 2009-12-24T12:57:05.327 回答
3

您可以使用哪些属性?您的应用程序关心哪些?例如,不可能有两个人在完全相同的时间在完全相同的时间出生在完全相同的地方,但您可能无法访问该准确度级别的数据!因此,您需要从您打算建模的属性中决定哪些属性足以提供可接受的数据完整性级别。无论您选择什么,您都正确地关注您选择的数据完整性方面(防止为同一个人插入多行)。

对于其他表中的 Joins/Foreign Keys,最好使用代理键。

我已经开始认为使用主键这个词是用词不当,或者充其量是令人困惑的。任何键,无论您将其标记为Primary KeyAlternate KeyUnique Key还是Unique Index,仍然是一个键,并且要求表中的每一行都包含键中属性的唯一值。从这个意义上说,所有的键都是等价的。更重要(最重要)的是它们是自然键(依赖于有意义的真实域模型数据属性)还是代理(独立于真实数据属性)

其次,同样重要的是您使用密钥的目的.. 代理键狭窄而简单并且永远不会改变(没有理由 - 它们没有任何意义)因此它们是连接或其他依赖项中的外键的更好选择表。

但是为了确保数据完整性,并防止为同一域实体插入多行,它们完全没用......为此,您需要某种Natural Key,从您可用的数据中选择,并且您的应用程序正在为其建模某种目的。

密钥不必是 100% 不可变的。例如,如果(例如)您使用姓名、电话号码和出生日期,即使某人更改了他们的姓名或电话号码,您也可以简单地更改表中的值。只要其他行的键属性中没有新值,就可以了。

即使您选择的密钥仅在 99.9% 的情况下有效,(假设您很不幸遇到两个姓名和电话号码相同的人,并且巧合地出生在同一天),那么您至少有 99.9%数据将被保证是准确和一致的 - 例如,您可以在他们的生日中添加时间以使其独一无二,或者在密钥中添加一些其他属性来区分它们。只要您不必因为更改而在整个数据库中更新外键中的数据值,(因为您没有将此键用作其他地方的 FK),您就不会面临任何重大问题。

于 2009-12-24T15:28:50.700 回答
1

使用自动生成的整数主键,然后对您认为应该唯一的任何内容施加唯一约束。但是 SSN 在现实世界中并不是唯一的,因此在此列上设置唯一性约束是一个坏主意,除非您认为因为数据库不接受客户而拒绝客户是一个好的商业模式。

于 2009-12-24T12:45:20.110 回答
1

我更喜欢自然键,但表person是一个丢失的案例。SSN 不是唯一的,也不是每个人都有一个。

于 2009-12-24T12:53:20.487 回答
1

我会推荐一个代理键。添加其他候选键所需的所有索引,但我的建议是将业务逻辑排除在键之外。

于 2009-12-24T13:22:34.230 回答
1

我更喜欢自然密钥,当它们可以信任时。

除非您经营一家银行或类似的公司,否则您的客户和用户没有理由为您提供有效的 SSN,甚至没有必要拥有一个。因此,出于商业原因,在您概述的情况下,您被迫不信任 SSN。对于“人”的任何给定的自然键,类似的论点将成立。

您别无选择,只能分配一个人工(阅读“代理”)键。它也可能是一个整数。确保它是足够大的整数,这样你就不需要很快扩展它。

于 2009-12-25T09:52:01.030 回答
0

添加到@Mark 和@Pascal(自动增量整数是你最好的选择)——SSN 很有用,应该正确建模。安全问题是应用程序逻辑的一部分。您可以将它们规范化到一个单独的表中,并且可以通过提供日期发布字段来使它们独一无二。

ps,对于那些不同意“应用程序中的安全性”观点的人,企业数据库将有一个细粒度的 ACL 模型;所以这不会是一个症结所在。

于 2009-12-24T12:51:44.920 回答