你如何确定什么应该是主键?

时间:2009-08-13 14:48:33

标签: sql mysql database-design

这是一个相当普遍的问题,但我想知道你在确定表的主键时使用了什么。您推荐的示例非常需要。

我注意到许多程序员添加了ID列并将其用作主键。我认为,从设计的角度来看,它存在缺陷,因为在这种情况下,ID与表格无关。

14 个答案:

答案 0 :(得分:12)

主键的作用是唯一标识表中的每一行。如果没有列或列集符合此要求,则通常会将包含唯一ID的列添加为主键。

我不同意您对程序员添加与表数据无关的ID的评论。当您需要跨多个表链接数据时,简洁的ID比复合键更容易使用。

答案 1 :(得分:5)

我在确定主键时的思维过程是这样的。

“此表中的一条记录将代表......?”

“对于Col X,Col Y,Col Z的不同值,表格中应该只有一行”,Cols X Y和Z是什么?“

CAR_MODEL表。

嗯,如果MANUFACTURER_NAME成为关键,这张表将存储有关不同类型汽车的信息吗?不,我可以有很多行识别同一制造商的不同车型。嗯,MANUFACTURER_NAME和MODEL_NAME应该是关键吗?不,我希望同一个MANUFACTURER_NAME和MODEL_NAME有不同的行,但同时表中的发布年份不同。那么“MANUFACTURER_NAME”,“MODEL_NAME”和“RELEASE_YEAR”呢。

我可以同时拥有两个同一个MANUFACTURER_NAME,MODEL_NAME和RELEASE_YEAR的行吗?嗯不。这没有意义,他们将是相同的汽车模型,我只想要每车型1记录。太棒了,这才是关键。

此表中的一条记录将代表特定制造商特定年份的特定型号。我在创建表时决定这一点,这就是我创建表的原因,如果你无法描述表格中的内容,那么有助于识别你不明白为什么要创建它的键。

随着时间的推移发生可怕的变化! (代理键,自然键,慢慢改变尺寸)

但是我存储的关于特定汽车模型(来自特定制造商和发行年)的信息可能会发生变化。最初我被告知它有两个门,现在我发现它有四个,我希望在我的表中有正确的信息,但不会丢失旧的记录,因为人们报告了它,我需要能够重现他们的旧结果

好的,我将添加一个新列“MODEL_ID”并使其成为表的主键,因此我可以存储具有相同型号名称,制造商名称和发行年份的多个记录。我还将添加valid_from和valid_to时间戳。

这可以很好地工作,事实上,在我的更改中,表的主键现在是MODEL_ID,一个代理键。但是自然键,商业密钥,“在任何时间点”的关键,仍然是Model_Name,Manufacturer_Name和Release_Year,我不能忽视它。

关于代理键的说明

根据定义,代理键对于每一行都是唯一的!代理键有时可以更轻松地处理数据,尤其是随时间变化的数据。但代理键不会以任何方式取代自然主键,您仍然需要知道表格的“颗粒”是什么。

如果我们说澳大利亚的每个人都会被分配一个Stack_Overflow_User_id当Jeff和Joel开始向狗和猫提供Stack_Overflow_User_Id和同一个人的多个ID时,我们会怎样做?

我们会说,“嘿Jeff和Joel,每个First_Name,Last_Name,Date_of_Birth和Place_of_Birth只发出1个ID!”。 *

我们需要知道自然键或者我们可以提供任何代理键!

(*那些所有这些相同的人怎么样?我们不需要护照号码或某种代理人吗?在实践中,代理人是好的和干净的,但它起源于哪里?最初它来自一个自然的键。)

答案 2 :(得分:3)

答案 3 :(得分:3)

您选择任何您知道的唯一值,最好是数字,例如客户ID或帐号。如果可能的话,远离基于字符串的键。如果没有别的,请使用GUID值或自动增量整数。

答案 4 :(得分:2)

密钥应该是一个列,其中每个条目都保证是唯一的。例子可能是社会保险号或驾驶执照号。理论上,您可以将多个列组合在一起形成复合键。因此,名称和出生日可能是独一无二的,因此它们可能是关键。然而在实践中没有人这样做,因为过表是一种痛苦。最佳解决方案通常是添加自动增量值或GUID列。

答案 5 :(得分:2)

你当然是Google首先对此有所了解,对吗?我看到,通过正确定义主键弹出的第一个结果也包含示例。

  • http://en.wikipedia.org/wiki/Unique_key
  • http://databases.about.com/cs/administration/g/primarykey.htm
  • http://msdn.microsoft.com/en-us/library/ms191236.aspx

  • 答案 6 :(得分:1)

    主键不一定必须是单个列,也可以是列的组合。正如Altherac's answer所述,它的目的是唯一地标识每一行。

    出于性能原因,最好使用小密钥,但根据系统的需要,使用的密钥类型可能会有很大差异。

    答案 7 :(得分:1)

    当我使用代理键时,在我看来性能会提高。我通常使用Int ID来提高性能。

    答案 8 :(得分:1)

    唯一标识您的条目所需的每个数据都应该是您的表ID。如果不存在这样的数据,则必须创建一个(最常见的是,使用正在运行的数字)。

    我不同意你的观点,即所有ID都应该与表有关,因为有时仅仅是唯一标识记录是不够的。此外,您必须使用多个ID,这比ID作为简单的运行号码更难处理。

    主键对于单个表来说相对简单,但是一旦你的条目分散在多个表上,事情就会变得混乱,特别是对于多对多的连接。在实施外键之前,还必须考虑使用外键。

    如果您希望专业地使用数据库(或希望通过本书进行操作),最好让自己熟悉Data Structure Diagrams

    编辑:Unified Modeling Language应该可以帮助您确定要用作主键的内容

    答案 9 :(得分:1)

    使用自然键,无论它们在哪里工作,都可以信任。如果将主题分析为实体和实体之间的关系(ER),则应该提供用于标识数据本身中的实体的键。如果某个实体的身份在数据本身中混淆,则发明一个人工密钥(通常称为代理密钥)。发明钥匙是最后的手段。

    当你去构建表时,一些表描述实体,而其他表描述关系。实体表获得与实体相同的密钥。关系表为参与关系的每个实体获取具有一个组件的复合键。有些关系不会得到自己的表(多对一)。相反,它们将通过向现有表添加外键来表示,因此它们不需要自己的主键。

    与使用每个表的发明ID字段相比,这会让你慢下来。但它会带来更好的数据管理,从而产生更好的数据。

    答案 10 :(得分:0)

    主键应始终是与您的数据无关的自动增量整数。

    编辑添加GUID也很好。重要的是密钥不会描述您的数据,因此如果您的数据发生变化,您的PK就不会。始终使用ID字段。

    考虑您使用电子邮件作为主键,然后用户更改其电子邮件地址。然后,您必须将该更改级联到每个连接的表。使用真实数据作为你的PK是没有意义的。

    答案 11 :(得分:0)

    好吧,在我们使用的一个系统中(我设计的),每个用户都有一个自动递增的主键作为其ID。与该特定用户相关的其他表也使用其ID作为其主键(尽管显然不是自动递增的),因此如果使用正确,它确实有意义。

    答案 12 :(得分:0)

    理论上可以使用任何独特的字段(例如社会安全号码,网址等),但实际上我认为使用自动生成的ID没有任何大的缺点。例如,一些古怪的错误会导致重复的SSN对您的数据造成灾难性后果。

    答案 13 :(得分:0)

    将其视为记录的唯一标识符(单列或多列)。

    想想指纹。你认为他们是个人独有的吗?它还没有被证实,但它确实看起来像一个不错的唯一标识符,直到人口变得如此之大以至于冗余蔓延。目前,这就像是识别你的记录的主键。 [1栏]

    如果我们的人口爆炸,指纹开始显示他们的弱点,我们可以将指纹和虹膜扫描结合起来,成为一个更强大的主键。 [2栏]

    主键通常是设计上唯一的,例如我们数据库中记录实例化时提供的ID号。

    至少,我希望这有助于理念。