在SQL Server中,IDENTITY如何不等于记录号



我一直在测试脚本性能(将开始和结束时间添加到RunTimeStats表中(。我有一个列叫ID,它被定义为INT PRIMARY KEY IDENTITY(1,1)

我想删除第7行之后的所有行,以删除与一些部分完成的记录相关的时间戳,这些记录是在一些新脚本无法完成时生成的,所以我运行了以下命令:

DELETE FROM dbo.RunTimeStats
WHERE ID > 7

我注意到,当我用新记录更新此表时,ID列不再等于记录8以后的记录编号。

请有人解释一下标识值是如何与实际SQL记录号不同步的?

此外,我计划开始使用事务来避免这种情况的发生!

IDENTITY只是一个任意的数,它与表中的行数无关。IDENTITY上的种子将在每次尝试INSERT时递增。当DELETE为一行时,IDENTITY值大于被删除行的行将不会更新为更低的数字。

之所以不能得到除"前7行"之外的所有内容,是因为ID的值和"行号"不相同。

来自标识(Transact-SQL(:

备注

标识列可用于生成键值。列上的identity属性保证以下内容:

  • 每个新值都是基于当前种子&定期的加薪

  • 特定事务的每个新值与表上其他并发事务不同。

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

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

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

  • 服务器重新启动或其他故障后的连续值-SQL server可能会出于性能原因和某些原因缓存标识值在数据库故障或服务器故障期间,分配的值可能会丢失重新启动。这可能会导致插入时标识值出现间隙。如果间隙是不可接受的,那么应用程序应该使用自己的生成键值的机制。使用具有NOCACHE选项可以将间隙限制为从不坚信的

  • 值的重用-对于具有特定种子/增量的给定标识属性,引擎不会重用标识值。如果特定的insert语句失败,或者如果insert语句被滚动那么消耗的身份值将丢失,并且不会再次生成。当后续标识生成值。

如果你想这样做,最好使用ROW_NUMBEROFFSET:

WITH CTE AS(
SELECT ID,
ROW_NUMBER() OVER (ORDER BY ID ASC) AS RN
FROM dbo.RunTimeStats)
DELETE FROM CTE
WHERE RN > 7;
WITH CTE AS(
SELECT ID
FROM dbo.RunTimeStats
ORDER BY ID OFFSET 7 ROWS)
DELETE FROM CTE;

删除行不会重新设定标识值的种子。另一方面,当表被截断时,标识列在这种情况下被重新设定为1。或者您可以使用以下语句手动重新设定种子,

DBCC CHECKIDENT('TABLE_NAME',重置,1(

最新更新