【发布时间】:2009-05-31 21:36:44
【问题描述】:
在您只需要 1 列作为键且该列中的值可以为整数的表中,何时不应使用标识字段?
相反,在同一个表和列中,你什么时候会手动生成它的值并且你不会为每条记录使用自动生成的值?
我想当表中有很多插入和删除时会出现这种情况。我对吗?还有哪些情况?
【问题讨论】:
在您只需要 1 列作为键且该列中的值可以为整数的表中,何时不应使用标识字段?
相反,在同一个表和列中,你什么时候会手动生成它的值并且你不会为每条记录使用自动生成的值?
我想当表中有很多插入和删除时会出现这种情况。我对吗?还有哪些情况?
【问题讨论】:
如果您已经选择了Great Primary Key Debacle 的代理方,那么我找不到不使用身份密钥的单一原因。通常的替代方案是 guid(它们有很多缺点,主要来自大小和随机性)和应用层生成的密钥。但是在应用程序层创建代理键比看起来要困难一些,并且不包括与应用程序无关的数据访问(即批量加载、导入、其他应用程序等)。一种特殊情况是分布式应用程序,此时 guid 甚至顺序 guid 可能会为站点 id + 身份密钥提供更好的替代方案。
【讨论】:
我想如果您要创建一个多对多链接表,其中两个字段都是foreign keys,则不需要标识字段。
现在我想大多数ORMs 期望在每个表中都有一个身份字段。一般来说,最好提供一个。
【讨论】:
我不确定我是否足够了解您的上下文,但我将您的问题解释为:
“如果我需要数据库创建一个唯一列(无论出于何种原因),它什么时候不应该是一个单调递增的整数(身份)列?”
在这些情况下,没有理由使用 DBMS 提供的工具以外的任何东西。在您的情况下(SQL Server?),这是一个身份。
除了:
如果您需要将表与其他来源的数据合并,请使用 GUID,这将防止重复键发生冲突。
【讨论】:
如果您需要合并数据库,则无需重新生成密钥会容易得多。
【讨论】:
不想要一个身份字段的一种情况是一对一的关系。辅助表将具有与主表相同的值作为其主键。在这种情况下拥有一个身份字段的唯一原因似乎是满足 ORM。
【讨论】:
您不能(通常)在插入标识列时指定值,例如,如果将“id”列指定为标识,则以下 SQL 将失败:
INSERT INTO MyTable (id, name) VALUES (1, 'Smith')
为了执行这种插入,您需要为该表启用 IDENTITY_INSERT - 这不打算正常启用,并且只能在任何时间点对数据库中最多 1 个表启用。
【讨论】:
如果我需要代理项,我会根据对全局唯一性的需要使用 IDENTITY 列或 GUID 列。
如果存在自然主键,或者主键被定义为其他外键的唯一组合,那么我通常没有 IDENTITY,也不会将其用作主键。
有一个例外,即我正在使用审计触发器跟踪的快照配置表。在这种情况下,通常有一个逻辑“主键”(通常是快照的日期和行的自然键——比如行是配置记录的成本中心或总帐帐号),而不是使用自然键“主键”作为主键,我添加一个 IDENTITY 并将其设为主键,并对日期和自然键创建唯一索引或约束。虽然理论上日期和自然键不应该改变,但在这些表中,如果用户这样做而不是添加新行并删除旧行,我想要审计(这反映了对其主键标识的行的更改) 以真正反映行中的变化 - 而不是键的消失和新键的出现。
【讨论】:
我最近在 C# 中实现了一个 Suffix Trie,它可以索引小说,然后允许以极快的速度完成搜索,与搜索字符串的大小成线性关系。部分需求(这是一个家庭作业)是使用离线存储,所以我使用了 MS SQL,并且需要一个结构来表示表中的节点。
我最终得到了以下结构:NodeID Character ParentID 等,其中 NodeID 是主键。
出于两个主要原因,我不希望将其作为自动递增标识。
【讨论】: