从0开始的SQL标识(1,1)

从0开始的SQL标识(1,1),sql,sql-server,tsql,identity,dbcc,Sql,Sql Server,Tsql,Identity,Dbcc,我有一个具有标识集的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 My

我有一个具有标识集的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

如果(在执行
插入之前)我检查了标识,它将返回null:

DBCC CHECKIDENT (MyTable, NORESEED)
正在检查标识信息:当前标识值“NULL”,当前列值“NULL”

我知道几种解决方法;我首先需要知道的是桌子是如何进入这种状态的

我知道
CHECKIDENT
返回null的唯一方法是,如果刚刚创建了表,但是
IDENTITY(1,1)
被接受,并且
INSERT
导致
SCOPE\u IDENTITY()
1

或者,如果我强制将
-1
作为当前种子(
DBCC CHECKIDENT(MyTable,RESEED,-1)
或使用
SET IDENTITY\u INSERT MyTable ON
),我可以将
0
作为下一个ID,但检查会报告当前
-1
种子(而不是null),因此不会发生这种情况


数据库如何进入列具有
IDENTITY(1,1)
DBCC CHECKIDENT(MyTable,NORESEED)
返回null的状态,但下一个
INSERT
导致
SCOPE_IDENTITY()
0

我希望有人/有东西运行:

DBCC CHECKIDENT ('dbo.MyTable', RESEED, 0);
如果运行以下命令:

CREATE TABLE dbo.MyTable(
    MyTableID int IDENTITY(1,1) NOT NULL,
    RecordName nvarchar(100) NULL
);

DBCC CHECKIDENT ('dbo.MyTable', RESEED, 0);
DBCC CHECKIDENT ('dbo.MyTable', NORESEED);
第二个
CHECKIDENT
仍然返回
NULL

正在检查标识信息:当前标识值“NULL”,当前列值“NULL”

但是,下一个标识值将为0。这是,MSDN声明:

当前标识值设置为新的“重新设定种子”值如果自创建表以来未向表中插入任何行,则执行DBCC CHECKIDENT后插入的第一行将使用新的_reseed_值作为标识。否则,插入的下一行将使用新的\u重设种子\u值+1。如果new_reseed_value的值小于identity列中的最大值,则在后续引用该表时将生成错误消息2627

这仅适用于新创建/截断的表,
sys.identity\u columns
中的
last\u value
列仍然为空。如上所述,如果要插入行、删除行,然后重新设定为0,则新标识仍然是1

完整测试脚本

IF OBJECT_ID(N'dbo.T', 'U') IS NOT NULL
    DROP TABLE dbo.T;

CREATE TABLE dbo.T(ID INT IDENTITY(1,1) NOT NULL);
INSERT dbo.T OUTPUT inserted.* DEFAULT VALUES;
-- OUTPUTS 1

DELETE dbo.T;
DBCC CHECKIDENT ('dbo.T', RESEED, 0);
INSERT dbo.T OUTPUT inserted.* DEFAULT VALUES;
-- OUTPUTS 1

TRUNCATE TABLE dbo.T;
DBCC CHECKIDENT ('dbo.T', RESEED, 0);
INSERT dbo.T OUTPUT inserted.* DEFAULT VALUES;
-- OUTPUTS 0

我假设表
MyTable
@HamletHakobyan上有一个触发器。该表上没有触发器。您在重新创建表时是否获得了相同的结果?如果您关心标识列的数值,则使用它们是错误的。您应该知道的是a)它们唯一地标识每一行,b)您可以将它们存储在数字列中。@Damien_不信者我们在代码中进行了优化,其中ID必须
=1
,然后才能进行DB调用的开销。这帮助我们避免了大量遗留代码中的N+1问题。如果这是在我们从头开始编写的代码库中,那么很容易避免。干杯!这就是问题所在-有人在应该调用DBCC CHECKIDENT(MyTable,RESEED,0)时调用了
DBCC CHECKIDENT(MyTable,RESEED)
。我不知道如果该表从未填充过,它仍然报告null作为当前标识。@Keith您的意思是说他们应该调用
DBCC CHECKIDENT(MyTable,NORESEED)