SQL Server是否会中断指定的身份种子增量?

时间:2014-01-20 16:17:30

标签: sql sql-server replication identity

我有两张表:table1(列id:种子1000,增量1)& table2(列id:种子2000,增量1)。首先,我在table1&中插入一些记录。 table2。第二,我在table2中插入table1(使用identity_insert_on),得到类似的内容:

1000 first_record_table1
1001 second_record_table1
1002 third_record_table1
2000 first_record_table2
2001 second_record_table2

第三:如果我在table1中添加一条新记录,我希望得到1003作为新id,但我得到2002。 (1003没有打破唯一的id规则,并且是table1的正确增量值,所以我没有看到任何理由跳转到最后一条记录并增加1,因为数据库似乎这样做)。

问题:如何获得1003作为新ID?

2 个答案:

答案 0 :(得分:4)

identity上的documentation非常明确:

  

列上的标识属性不保证以下内容:

     
      
  • 值的唯一性 - 必须使用PRIMARY KEY或UNIQUE约束或UNIQUE索引强制执行唯一性。

  •   
  • 事务中的连续值 - 插入多行的事务不能保证获得行的连续值,因为表上可能会出现其他并发插入。如果值必须是连续的,那么事务应该使用表上的独占锁或使用SERIALIZABLE隔离级别。

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

  •   
  • 重用值 - 对于具有特定种子/增量的给定标识属性,引擎不会重用标识值。如果特定的insert语句失败或者回滚insert语句,则消耗的标识值将丢失,并且不会再次生成。生成后续标识值时,这可能会导致间隙。

  •   

在大多数情况下,identity primary key列只会执行预期的操作。插入新行时,它会创建一个大于任何先前值的新值。可能存在差距,但这不是主键的问题。

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

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

答案 1 :(得分:1)

增量1只表示下一条记录的ID大于最大记录的ID,而不是将使用所有数字。如果你想让1003作为新的ID,你必须自己做一些编程,并处理一旦达到2000就已经采用新的情况。

但是你永远不应该依赖任何生成的ID没有间隙。想象一下,你有2个课程。第一个会话插入一些东西,但尚未提交或回滚。第二个会话插入一些东西并提交。第一场会议回滚。你想怎么处理这个案子?您需要为第一个会话分配一些ID,并为第二个会话分配不同的ID。现在第一个会话回滚,因此其ID未使用。你想从第二个会话的ID中减去一个吗?非常糟糕的主意。阻止第二个会话,直到第一个回滚或已提交?非常糟糕的主意。

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