简体   繁体   English

SQL Server中断分配的标识种子增量?

[英]SQL Server breaks the assigned identity seed increment?

I have two tables: table1 (column id : Seed 1000, increment 1) & table2 (column id : Seed 2000, increment 1). 我有两个表: table1 (列id :种子1000,增量1)和table2 (列id :种子2000,增量1)。 First I insert some records in table1 & table2 . 首先,我在table1table2插入一些记录。 Second I insert to table2 in table1 (using identity_insert_on ) and get something like: 其次,我在table1插入table2 (使用identity_insert_on ),并得到如下信息:

1000 first_record_table1
1001 second_record_table1
1002 third_record_table1
2000 first_record_table2
2001 second_record_table2

Third: If I add a new record in table1, i expect to get 1003 as the new id but i get 2002. (1003 is not breaking the unique id rule and is the correct increment value for table1, so I don't see any reason to jump to the last record and increment 1, as the database seems to do). 第三:如果我在表1中添加新记录,我希望获得1003作为新ID,但我得到2002。(1003没有违反唯一ID规则,并且是表1的正确增量值,因此我看不到任何记录跳到最后一个记录并递增1的原因,就像数据库似乎这样做的那样)。

Question: How can I get 1003 as the new id? 问题:如何获得1003作为新ID?

The documentation on identity is quite clear: 关于identity文档非常清楚:

The identity property on a column does not guarantee the following: 列上的identity属性不能保证满足以下条件:

  • Uniqueness of the value – Uniqueness must be enforced by using a PRIMARY KEY or UNIQUE constraint or UNIQUE index. 值的唯一性–必须通过使用PRIMARY KEY或UNIQUE约束或UNIQUE索引来强制执行唯一性。

  • Consecutive values within a transaction – A transaction inserting multiple rows is not guaranteed to get consecutive values for the rows because other concurrent inserts might occur on the table. 事务内的连续值–不能保证插入多行的事务会获得行的连续值,因为表上可能会发生其他并发插入。 If values must be consecutive then the transaction should use an exclusive lock on the table or use the SERIALIZABLE isolation level. 如果值必须是连续的,则事务应在表上使用排他锁或使用SERIALIZABLE隔离级别。

  • Consecutive values after server restart or other failures –SQL Server might cache identity values for performance reasons and some of the assigned values can be lost during a database failure or server restart. 服务器重新启动或其他故障后的连续值–由于性能原因,SQL Server可能会缓存标识值,并且在数据库故障或服务器重新启动期间某些分配的值可能会丢失。 This can result in gaps in the identity value upon insert. 这可能导致插入时身份值出现空白。 If gaps are not acceptable then the application should use a sequence generator with the NOCACHE option or use their own mechanism to generate key values. 如果差距不可接受,则应用程序应使用带有NOCACHE选项的序列生成器,或使用其自己的机制生成键值。

  • Reuse of values – For a given identity property with specific seed/increment, the identity values are not reused by the engine. 值的重用–对于具有特定种子/增量的给定身份属性,引擎不会重用身份值。 If a particular insert statement fails or if the insert statement is rolled back then the consumed identity values are lost and will not be generated again. 如果特定的插入语句失败或插入语句回滚,则使用的标识值将丢失并且不会再次生成。 This can result in gaps when the subsequent identity values are generated. 当生成后续标识值时,这可能会导致出现间隙。

In most cases, an identity primary key column does just what it is intended to do. 在大多数情况下, identity primary key列可以完成其预期的工作。 It creates a new value bigger than any previous value when a new row is inserted. 当插入新行时,它将创建一个大于任何先前值的新值。 There may be gaps, but that is not a problem for a primary key. 可能存在差距,但这对于主键来说不是问题。

If you want a column that fills in gaps, then you will have to write a trigger to assign the values. 如果要填充空白的列,则必须编写触发器以分配值。

Alternatively, you could just use row_number() in queries to get sequential values. 另外,您可以在查询中使用row_number()来获取顺序值。

Increment 1 just means the next record will have an ID that's one larger than the largest one, not that all numbers will be used. 增量1仅表示下一条记录的ID比最大的ID大一个,而不是将使用所有数字。 If you want the 1003 as the new ID, you'll have to do some programming yourself, and handle the case that the new is already taken once you reach 2000. 如果要使用1003作为新ID,则必须自己进行一些编程,并处理达到2000时已经采用新ID的情况。

But you should never ever rely on any generated IDs being without gaps. 但是,您永远不应依赖任何生成的ID。 Imagine you have 2 sessions. 假设您有2节课。 First session inserts something and does not commit nor rollback yet. 第一个会话插入了一些内容,尚未提交或回滚。 Second session inserts something and commits. 第二会话插入一些东西并提交。 First session rolls back. 第一届会议回滚。 How do you want to handle this case? 您要如何处理这种情况? You will need to assign some ID to the first session, and a different ID to the second one. 您将需要为第一个会话分配一些ID,为第二个会话分配一个不同的ID。 Now the first session rolls back, so its ID is unused. 现在,第一个会话回滚,因此其ID未使用。 Do you want to subtract one from the second session's ID? 您是否要从第二个会话的ID中减去一个? Very bad idea. 好主意。 Block the 2nd session until the 1st one has either rolled back or committed? 阻止第二个会话,直到第一个会话回滚或提交? Very bad idea as well. 也是个坏主意。

So please forget about consecutive IDs, they will never work. 因此,请忘记连续的ID,它们将永远无法使用。 Unique IDs are what you normally need, and SQL Server guarantees them. 唯一的ID通常是您需要的,并且SQL Server保证它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM