【发布时间】:2014-03-05 14:00:43
【问题描述】:
我有一个带有标识集的 SQL 表:
CREATE TABLE MyTable(
MyTableID int IDENTITY(1,1) NOT NULL,
RecordName nvarchar(100) NULL)
这个表发生了一些事情,导致了奇怪的行为。我需要弄清楚是什么。
当插入发生时:
INSERT MyTable(RecordName)
VALUES('Test Bug')
SELECT SCOPE_IDENTITY() -- returns 0
SELECT * FROM MyTable -- displays: 0, 'Test Bug'
这是一个问题,因为此插入上方的代码要求第一个 ID 为 1 - 我无法弄清楚 IDENTITY(1,1) 如何以 0 结尾。
如果(在执行 INSERT 之前)我检查它返回 null 的身份:
DBCC CHECKIDENT (MyTable, NORESEED)
检查身份信息:当前身份值'NULL',当前列值'NULL'。
我知道有几种方法可以解决这个问题;我首先需要知道桌子是如何进入这种状态的?
我知道 CHECKIDENT 返回 null 的唯一方法是如果表刚刚创建,但随后 IDENTITY(1,1) 被兑现并且 INSERT 导致 SCOPE_IDENTITY() 成为 1。
或者,如果我强制 -1 作为当前种子(DBCC CHECKIDENT (MyTable, RESEED, -1) 或 SET IDENTITY_INSERT MyTable ON),我可以将 0 作为下一个 ID,但随后检查报告当前 -1 种子(而不是 null) ,所以这不可能是发生的事情。
数据库是如何进入列有IDENTITY(1,1),DBCC CHECKIDENT (MyTable, NORESEED)返回null,但下一个INSERT导致SCOPE_IDENTITY()为0的状态?
【问题讨论】:
-
我假设表
MyTable上有一个触发器。 -
@HamletHakobyan 该表上没有触发器。
-
重新建表时是否达到了同样的结果?
-
如果你关心标识列的数值,那你就用错了。您应该知道的是 a) 它们唯一标识每一行,b) 您可以将它们存储在数字列中。
-
@Damien_The_Unbeliever 我们在代码中进行了优化,其中 ID 必须为
>=1,然后才会产生 DB 调用的开销。这帮助我们避免了大量遗留代码中的 N+1 问题。如果这是在我们从头开始编写的代码库中,这很容易避免。
标签: sql sql-server tsql identity dbcc