从0开始的SQL标识(1,1)
我有一个具有标识集的SQL表:从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
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)
?