在设计表时,我养成了一个习惯,即有一个唯一的列,并将其作为主键。这可以通过三种方式实现,具体取决于需求:

自动递增的标识整数列。 唯一标识符(GUID) 短字符(x)或整数(或其他相对较小的数字类型)列,可作为行标识符列

数字3将用于相当小的查找,主要是读取表,这些表可能有一个唯一的静态长度字符串代码,或一个数值,如年或其他数字。

在大多数情况下,所有其他表都有一个自动递增的整数或唯一标识符主键。

问题:-)

我最近开始使用一些数据库,这些数据库没有一致的行标识符,而且主键目前聚集在各个列之间。一些例子:

datetime /字符 datetime /整数 datetime / varchar 字符/ nvarchar / nvarchar

这有有效的理由吗?我总是为这些情况定义一个标识符或唯一标识符列。

此外,还有许多根本没有主键的表。如果有的话,合理的理由是什么?

我试图理解为什么桌子被设计成这样,对我来说,它似乎是一个很大的混乱,但也许有很好的理由。

第三个问题在某种程度上帮助我解析答案:在使用多个列组成复合主键的情况下,与代理/人工键相比,这种方法是否有特定的优势?我主要考虑的是性能、维护、管理等方面。


当前回答

从不同的字段中创建主键是没有问题的,这是一个自然键。

您可以使用Identity列(与候选字段上的唯一索引相关联)来创建代理键。

这是一个古老的讨论。在大多数情况下,我更喜欢代理键。

但是没有钥匙是没有理由的。

再保险:编辑

是的,关于这一点有很多争议:D

我没有看到任何明显的优势自然键,除了他们是自然的选择。你总是会用Name、SocialNumber或者类似的东西来思考,而不是idPerson。

代理键可以解决自然键存在的一些问题(例如传播更改)。

当你习惯了代理,它似乎更干净,更易于管理。

但最终,你会发现这只是一个品味或心态的问题。有些人用自然的钥匙能“更好地思考”,而其他人则不然。

其他回答

表应该一直有一个主键。如果没有,它应该是一个自动递增字段。

有时人们会省略主键,因为他们要传输大量数据,这可能会减慢(取决于数据库)进程。但是,它应该加在它之后。

一些关于链接表的评论,这是正确的,这是一个例外,但是字段应该是FK以保持完整性,并且在某些情况下,如果链接中的重复没有被授权,这些字段也可以是主键…但是要保持简单的形式,因为异常在编程中经常出现,所以应该提供主键来保持数据的完整性。

我遵循一些规则:

Primary keys should be as small as necessary. Prefer a numeric type because numeric types are stored in a much more compact format than character formats. This is because most primary keys will be foreign keys in another table as well as used in multiple indexes. The smaller your key, the smaller the index, the less pages in the cache you will use. Primary keys should never change. Updating a primary key should always be out of the question. This is because it is most likely to be used in multiple indexes and used as a foreign key. Updating a single primary key could cause of ripple effect of changes. Do NOT use "your problem primary key" as your logic model primary key. For example passport number, social security number, or employee contract number as these "natural keys" can change in real world situations. Make sure to add UNIQUE constraints for these where necessary to enforce consistency.

关于代理键和自然键,我参考了上面的规则。如果自然键很小并且永远不会改变,则可以将其用作主键。如果自然键很大或可能改变,我使用代理键。如果没有主键,我仍然会创建一个代理键,因为经验表明,您总是会向模式添加表,并希望在适当的位置放置一个主键。

我怀疑原始数据结构的设计者需要Steven A. Lowe的卷起报纸疗法。

顺便说一句,guid作为主键可能会影响性能。我不推荐。

自然键和人工键是数据库社区中的一种宗教争论——请参阅本文及其链接的其他文章。我既不赞成一直使用人工钥匙,也不赞成永远不使用。我会根据具体情况做出决定,例如:

美国各州:我会使用state_code(德克萨斯州的'TX'等),而不是德克萨斯州的state_id=1 员工:我通常会创建一个人工的employee_id,因为很难找到其他任何工作。SSN或同等的工作,但可能会有问题,如新加入谁还没有提供他/她的SSN。 员工薪资历史:(employee_id, start_date)。我不会创建一个人工的employee_salary_history_id。它能起到什么作用(除了“愚蠢的一致性”)

无论在哪里使用人工键,都应该始终在自然键上声明唯一的约束。例如,如果你必须使用state_id,但是你最好在state_code上声明一个唯一的约束,否则你最终肯定会得到:

state_id    state_code   state_name
137         TX           Texas
...         ...          ...
249         TX           Texas

从不同的字段中创建主键是没有问题的,这是一个自然键。

您可以使用Identity列(与候选字段上的唯一索引相关联)来创建代理键。

这是一个古老的讨论。在大多数情况下,我更喜欢代理键。

但是没有钥匙是没有理由的。

再保险:编辑

是的,关于这一点有很多争议:D

我没有看到任何明显的优势自然键,除了他们是自然的选择。你总是会用Name、SocialNumber或者类似的东西来思考,而不是idPerson。

代理键可以解决自然键存在的一些问题(例如传播更改)。

当你习惯了代理,它似乎更干净,更易于管理。

但最终,你会发现这只是一个品味或心态的问题。有些人用自然的钥匙能“更好地思考”,而其他人则不然。