主键是否应始终从1开始?

4
我正在迁移一份旧的数据库(Oracle),其中有几个表如CountryCodeDeptCodeRoleCodes,它们的主键是字符串(Codes)。我正在考虑添加一个数字列作为主键,因为这样可以更快地使用joins。这些表的大小并不是很大。
我想知道这些表的主键是否应该从数字“1”开始,或者它们可以从100开始,只是为了区分不同的表的主键,尽管我不认为我会在报告中显示它们。

您通常可以在表设计器(在MSSQL服务器中)中设置初始种子 - 这样做完全没问题。 - Dave Bish
3
主键的值并不重要,只要一个表中不存在重复的键即可。两个表之间的主键关系不应该困扰你,你只需要考虑一张表的主键和另一张表的外键(它们必须匹配)。 - oleksii
9个回答

3

你不应该这样做来区分表格,因为这并不实用。

并非所有主键都必须以1开始,例如订单号。


如果主键从不同的范围开始,则有助于测试报告。 - user1263981

3
对于由序列生成的ID,如果容易实现,我建议从不同的值开始(这取决于你的数据库等)。你不应该在代码中使用它们来区分它们,但这可以使测试更加合理。
之前,我曾经遇到过这样一种情况,我意外地将一个表的外键用作另一个表的外键。测试通过了,因为ID恰好相同。后来我们发现问题后,我们更改了起始值,发现测试结果更加清晰。

2

你使用的理由切换到整数主键似乎不太合理:相比于原来的代码(我假设是字符串),使用INT而获得的性能提升将会微不足道。主键总是被索引的,对于字符串或数字的索引同样快速。因此,除非你真的需要一个INT,否则我倾向于保持原始数据类型并使用原始数据 - 这简化了数据迁移(这是在进行任何工作时都应该考虑的事情)。


谢谢,这正是我刚想到的。另外,将EmpCode(Varchar2)作为PK是否可以?该表中有大约600行引用了timesheet和employee history表。 - user1263981
我不认为有什么问题。在编写参考数据表时,索引的选择比您编码字段是字符串还是数字更重要。如果整数更快,那只是因为它们是固定的4字节值,而字符串可能是随机长度(最大字符串字段大小)。因此,如果您的编码字段是(例如)VARCHAR2(10),那么就没有问题。但是,如果字符串大小显着较长,则会感到担忧,因为这不是真正的代码(“代码”意味着短字符串)。 - Chris J
@SteveDog - 我想这取决于你为什么要有一个代码列。对我来说,如果你有一个代码,这是其他某些东西的简写形式,因此你可能会有一个基于ISO3166的国家代码列表,将代码映射到全名。代码很少会改变。如果您决定粘贴唯一数字并PK它(给出代理键),那么您还需要在代码上拥有唯一索引(有效地给出自然键)以防止重复代码,因此您几乎没有获得任何东西。我想这归结于数据:当您知道数据是什么时,您可以决定最佳PK。 - Chris J
当前系统中定义了VARCHAR(20),我一定会将其减少。我喜欢你提出的三列(前缀,INT,代码)的想法,但在当前系统中,所有员工代码都与国家相关,例如英国员工代码以UK001开头,法国员工代码以FR001开头,等等。此外,我需要将员工历史记录保留在历史表中(慢速维度更改),这如何适应您的选项?我还将迁移所有员工代码到新系统中,因为它涉及到非常大的Timesheet表。 - user1263981
我正在重写时间表应用程序,包括重新设计数据库,我们只使用Oracle,因此迁移将在同一数据库上进行(从Oracle到Oracle)。 当前员工代码以字母数字形式表示,例如“UK001”,“UK002”,“FR001”,“FR002”,并且此员工代码字段被用作主键。员工表还链接到时间表和其他表,其中EmpCode被引用为FK。 我曾考虑在新数据库中添加新的INT列,并将其保留为PK,但现在您也提到了最好将EmpCode保留为PK并缩短数据类型的长度。 - user1263981
显示剩余6条评论

1

在ERP系统中,定义代表某个物品组的数字范围非常普遍。

这可以作为更大数字中的位置,例如:

1234567890
   | |
   index 4 - 6 represents region code
   index 7 - 8 represents dept code... 

或者,就像我怀疑你的情况一样,在同一个位置的不同部分,比如

1000 - 1999 Region codes
2000 - 2999 DeptCode
3000 - 3999 RoleCode

因此:不一定必须以1开头。
更大的ERP系统甚至有数字范围的配置部分!
现在,从数据库角度来看:
是的,您的表应该始终具有主键!拥有一个主键将极大地提高平均情况下的性能。 (但在大多数数据库系统中,如果您没有提供一个主键,DBMS会设置一个,您看不到也无法处理。一些DBMS甚至会创建索引,但这是另外的事情)

1

我认为起始数字或起始值并不重要,它们将持有主键。重要的是,在联接表的外键中,它们将用与主表主键相同的值表示。


1

代理键可以具有任何值,只要它们是唯一的。这就是为什么它被称为“代理”的原因 - 值本身没有固有的含义,通常甚至不应该向用户显示。话虽如此,您可以考虑使用不同的种子进行测试,就像Jon Skeet建议的那样

话虽如此,您真的需要引入新的(代理)键吗?现有的自然键实际上可能会导致1更少的连接,并且可能对聚集有用。虽然代理键有合法用途,但不要仅仅因为它“时髦”而这样做 - 要始终注意您所做出的权衡,并选择适合您具体需求的正确平衡。


1它会自动“传播”到外键,因此您不需要将子表连接到父表以获取自然键 - 自然键已经在子表中。


+1,但是使代理成为代理的原因是它取代了自然键。 (代理的意思是“替代”或“取代”某物。) - Mike Sherrill 'Cat Recall'
@Catcall,我不太能用英语争论,因为这不是我的母语。但在数据库中,代理键不仅仅是任何替代品,它是一种不同“质量”的替代品。备用键可以很容易地取代主键,但我们(不一定)称其为“代理键”。只有当其值具有某种质量(缺乏含义)时,我们才称其为代理键。 - Branko Dimitrijevic

0

主键从哪个整数开始并不重要。 假设代码不经常更新,我认为整数不会更快。它更依赖于它是一个varchar还是已知大小。


0

我个人总是将一个名为“Id”的字段作为表的主键,定义为int或bigInt(如果需要)。

如果表与枚举类型匹配,则我会确保Id与枚举类型id匹配,该id可以是任何数字-因此不需要从1开始。

如果它不匹配枚举类型,则通常会使用自动递增键从1开始,但这并不总是必要的。

请注意-如果行数很少,则在数字和varchar上进行索引的差异将是微不足道的。


但是代码使用的表非常大,所以您认为在主键(Varchar2数据类型)上运行JOINS会更快。 - user1263981
我不知道你说的“大”是什么意思,但是使用整数而不是 varchar 进行连接确实会更快——表越大,性能差异就越大。我个人尽量避免在 ID 上进行连接。 - BonyT

0

是的,它起始于哪个整数并不重要,它的主要作用是唯一地定义行并在其他表之间建立关系。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接