我目前正在研究其他人的数据库,其中主键是通过包含表名列表和最后使用的主键的查找表生成的。存储过程会增加该值并检查它的唯一性,然后再将其返回给调用“插入”SP。
使用这样的方法(或仅生成 GUID)而不是仅使用身份/自动编号有什么好处?
我不是在谈论实际上“意味着”诸如 ISBN 或产品代码之类的主键,只是唯一标识符。
谢谢。
我目前正在研究其他人的数据库,其中主键是通过包含表名列表和最后使用的主键的查找表生成的。存储过程会增加该值并检查它的唯一性,然后再将其返回给调用“插入”SP。
使用这样的方法(或仅生成 GUID)而不是仅使用身份/自动编号有什么好处?
我不是在谈论实际上“意味着”诸如 ISBN 或产品代码之类的主键,只是唯一标识符。
谢谢。
在您使用复制的情况下,自动生成的 ID 可能会导致问题(我相信您发现的技术可以!)。在这些情况下,我通常选择 GUID。
如果您不太可能使用复制,那么自动递增的 PK 很可能会正常工作。
使用自动编号本身并没有错,但有一些理由不这样做。尽管如此,正如 dacracot 所说,推出自己的解决方案并不是最好的主意。让我解释。
不在每个表上使用自动编号的第一个原因是您最终可能会合并来自多个表的记录。假设您有一个 Sales Order 表和一些其他类型的 order 表,并且您决定提取一些公共数据并使用多表继承。拥有全局唯一的主键很好。这类似于 bobwienholt 所说的合并数据库,但它可以发生在数据库中。
其次,其他数据库不使用这种范例,而其他范例(例如 Oracle 的序列)要好得多。幸运的是,可以使用 SQL Server 模拟 Oracle 序列。一种方法是为整个数据库创建一个自动编号表,称为 MainSequence 或其他。数据库中没有其他表将使用自动编号,但任何需要自动生成主键的人都将使用 MainSequence 来获取它。这样,您无需自己构建即可获得 dacracot 所谈论的所有内置性能、锁定、线程安全等。
另一种选择是将 GUID 用于主键,但我不建议这样做,因为即使您确定人类(甚至是开发人员)永远不会阅读它们,也可能有人会阅读它们,而且这很难。更重要的是,在 T-SQL 中很容易隐式转换为整数,但隐式转换为 GUID 会遇到很多麻烦。基本上,它们是不方便的。
在构建新系统时,我建议使用专用表来生成主键(就像 Oracle 序列一样)。对于现有的数据库,我不会特意去改变它。
来自编码恐怖:
GUID 优点
GUID 缺点
这篇文章提供了很多关于决定 GUID 还是自动增量的良好外部链接。如果可以的话,我会选择 GUID。
递增的过程方法必须是线程安全的。如果没有,您可能无法获得唯一编号。另外,速度一定要快,否则会成为应用瓶颈。内置函数已经考虑了这两个因素。
客户端能够预先分配一大堆 ID 以进行批量插入,而不必随后使用插入的 ID 更新其本地对象,这很有用。然后是整个复制问题,正如 Galwegian 所提到的。
这是自动递增整数作为键的事情:
您必须先发布记录,然后才能访问它。这意味着,在您发布记录之前,您不能,例如,准备将存储在另一个表中的相关记录,或者许多其他可能的原因中的任何一个,这些原因可能有助于访问新记录的唯一性id,在发布之前。
以上是我的决定因素,是采用一种方法还是另一种方法。
使用唯一标识符将允许您合并来自两个不同数据库的数据。
也许您有一个应用程序在多个数据库中收集数据,然后在一天中的不同时间与主数据库“同步”。在这种情况下,您不必担心主键冲突。
或者,您可能想在实际创建记录之前知道它的 ID。
我对自动递增键的主要问题是它们没有任何意义
在我看来,这是对主键的要求——除了识别记录之外没有其他理由存在。如果它没有现实世界的意义,那么它就没有现实世界的改变理由。一般来说,您不希望主键更改,因为您必须搜索替换整个数据库或更糟。我对那些我认为是独一无二的、不变的事情感到惊讶,但几年后并没有发生。
一个好处是它可以让数据库/SQL 更加跨平台。SQL 可以在 SQL Server、Oracle 等上完全相同...
我能想到的唯一原因是代码是在sequences
发明之前编写的,而代码忘记了;)
对于大多数帖子的当前方法对我有意义的场景(复制是可能的),我更愿意使用 GUID。如果复制是问题,那么这样的存储过程必须知道必须链接的其他服务器以确保密钥的唯一性,这将使其非常脆弱并且可能是一种糟糕的方法。
我使用不是自动递增标识的整数主键的一种情况是强制外键约束的很少更改的查找表的情况,它将在数据消耗应用程序中具有相应的枚举。在那种情况下,我想确保枚举映射在开发和部署之间是正确的,尤其是在有多个产品服务器的情况下。
另一个潜在的原因是您故意想要随机密钥。例如,如果您不希望爱管闲事的浏览器浏览您在数据库中的每个项目,这可能是可取的,但它并不足以保证实际的身份验证安全措施。
使用 GUID 主键而不是自动递增主键的一个有用的附带好处是,您可以为客户端的新行分配 PK 值(实际上您必须在复制场景中执行此操作),从而节省您的检索您刚刚在服务器上添加的行的 PK 的麻烦。
GUID PK 的缺点之一是 GUID 字段上的连接速度较慢(除非最近发生了变化)。使用 GUID 的另一个好处是尝试向非技术经理解释为什么 GUID 冲突不太可能发生是很有趣的。
我对自动递增键的主要问题是它们没有任何意义。
对于某些字段提供唯一性(无论是单独还是与另一个字段组合)的表,我会选择使用它。
Galwegian 的回答不一定正确。
使用 MySQL,您可以为每个数据库实例设置一个键偏移量。如果你将它与足够大的增量结合起来,它会很好。我确信其他供应商会有某种类似的设置。
假设我们有 2 个要复制的数据库。我们可以通过以下方式进行设置。
increment = 2
db1 - offset = 1
db2 - offset = 2
这意味着
db1 将具有键 1、3、5、7....
db2 将具有键 2、4、6、8....
因此,我们不会在插入时发生键冲突。
这样做的唯一真正原因是与数据库无关(如果不同的数据库版本使用不同的自动编号技术)。
这里提到的另一个问题是在多个地方创建记录的能力(比如在中心办公室以及在旅行用户的笔记本电脑上)。但是,在这种情况下,您可能需要类似“站点代码”之类的东西,该代码对于每个安装都唯一,并以每个 ID 为前缀。