2014-01-20 38 views
1

我有两个表:table1(列id:种子1000,增量1)& table2(列id:种子2000,增量1)。首先,我在table1 & table2插入一些记录。其次,我要插在table2table1(使用identity_insert_on)和得到的东西,如:SQL服务器打破了分配的标识种子增量?

1000 first_record_table1 
1001 second_record_table1 
1002 third_record_table1 
2000 first_record_table2 
2001 second_record_table2 

第三:如果我在表1中添加一个新的记录,我期望能获得1003作为新的ID,但我得到2002 ( 1003不破的唯一ID规则,并且是table1的正确的增值,所以我看不出有任何理由要跳转到最后一个记录和增量1,作为数据库似乎做)。

问:我怎样才能获得1003新的ID?

+1

它是SQL Server 2012? –

+0

如果你正在做的插入idnetity_insert设置你不应该使用身份证,你完全误解了一个自动生成的密钥是什么。 – HLGEM

回答

4

identitydocumentation是相当清楚的:

列上的标识属性不保证以下几点:

  • 价值的独特性 - 唯一性,必须使用PRIMARY强制执行KEY或UNIQUE约束或UNIQUE索引。在一个事务中

  • 连续值 - 事务插入多行不保证,因为其他并发插入可能会在桌子上出现以获取行连续值。如果值必须连续,那么事务应该在表上使用排它锁或使用SERIALIZABLE隔离级别。

  • 服务器重启或其他故障后的连续值 - 出于性能原因,SQL Server可能会缓存标识值,并且在数据库故障或服务器重新启动期间,某些分配的值可能会丢失。这可能导致插入时身份值的差距。如果差距不可接受,那么应用程序应该使用具有NOCACHE选项的序列发生器或使用它们自己的机制来生成关键值。

  • 值的重用 - 对于种子特异性/增量给定的身份属性,标识值不被发动机重新使用。如果某个特定的插入语句失败或者插入语句回滚,则所消耗的标识值将丢失,并且不会再次生成。当生成后续标识值时,这可能导致间隙。

在大多数情况下,identity primary key列不只是它是什么打算这样做。当插入新行时,它创建一个比以前任何值都大的新值。可能存在差距,但这不是主键的问题。

如果你想要一个填补空白的列,那么你将不得不编写一个触发器来分配值。

或者,您可以在查询中使用row_number()以获取顺序值。

+0

对于任何回滚的记录以及任何已删除的记录都会有空白。这是设计中的一个因素,它可以使其有效地使IDS发生异化。你永远不应该期望自动生成的密钥不跳过数字。关心数字是否被跳过也没有意义,自动生成的键应该没有意义。 – HLGEM

+0

我知道种子只用于第一个记录,max(id)用于任何其他记录?试图映射规则。 – gtryonp

+0

@ user2934862。 。 。 'max(id)+ 1'可能不会用于下一个ID。下一个ID可能更大。 SQL Server保留一次“保留”多个ID的权利,即使它们都未被使用。 –

1

增量1只意味着下一个记录的ID将比最大的ID大1,而不是所有的数字都会被使用。如果你想1003作为新的ID,你必须自己做一些编程,并处理新的情况下,已经采取一旦你达到2000.

但你永远不应该依靠任何生成的ID是没有空白。想象一下你有2个会话。第一次会话插入一些内容,但不提交也不回滚。第二次会话插入一些东西并提交。第一次会议回滚。你想如何处理这种情况?您需要为第一个会话分配一些ID,并为第二个会话分配一个不同的ID。现在第一个会话回滚,所以其ID不被使用。你想从第二个会话的ID中减去一个吗?非常糟糕的主意。阻止第二届会议,直到第一届会议回滚或承诺?非常糟糕的想法。

所以请忘记连续的ID,他们将永远不会工作。唯一的ID是您通常需要的,并且SQL Server保证它们。

+0

感谢您的评论。差距不是我关心的问题:这是关于为什么数据库引擎在出现冲突之前打破“种子...增量”规则。看起来种子仅用于第一条记录,max(id)用于任何其他记录 – gtryonp