DBCC CHECKIDENT将Identity设置为0

我正在使用此代码重置表上的身份:

DBCC CHECKIDENT('TableName', RESEED, 0) 

这大部分时间工作正常,第一次插入我插入1到Id列。 但是,如果我删除数据库并重新创build它(使用我写的脚本),然后调用DBCC CHECKIDENT,插入的第一项将具有0的ID。

有任何想法吗?

编辑:经过研究后,我发现我没有正确阅读文档: http : //msdn.microsoft.com/en-us/library/aa258817(SQL.80).aspx – “当前标识值设置为new_reseed_value。如果创build后没有行插入到表中,执行DBCC CHECKIDENT后插入的第一行将使用new_reseed_value作为标识,否则插入的下一行将使用new_reseed_value + 1。

正如你在你的问题中指出的那样,这是一个logging的行为 。 我仍然觉得很奇怪。 我用来重新填充testing数据库,即使我不依赖于标识字段的值,当从头开始填充数据库并在删除所有数据并重新填充之后,有一些令人讨厌的问题,那就是有不同的值。

一个可能的解决scheme是使用截断清理表而不是删除。 但是之后你需要放下所有的约束,然后重新创build它们

通过这种方式,它总是作为一个新创build的表,并且不需要调用DBCC CHECKIDENT。 第一个标识值将是表定义中指定的值,无论您是第一次插入数据还是第N次插入数据

你在编辑你的问题时写的是正确的。

运行DBCC CHECKIDENT('TableName', RESEED, 0)
– 新创build的表格将以标识0开始
– 现有表格将以身份标识1继续

解决scheme是在下面的脚本,这是一个穷人男子截断:)

 -- Remove all records from the Table DELETE FROM TableName -- Use sys.identity_columns to see if there was a last known identity value -- for the Table. If there was one, the Table is not new and needs a reset IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = 'TableName' AND last_value IS NOT NULL) DBCC CHECKIDENT (TableName, RESEED, 0); 

更改语句

  DBCC CHECKIDENT('TableName', RESEED, 1) 

这将从2开始(或重新创build表时为1),但不会为0。

另请参阅: http : //sqlblog.com/blogs/alexander_kuznetsov/archive/2008/06/26/fun-with-dbcc-chekident.aspx

这是logging的行为,为什么如果您重新创build表,运行CHECKIDENT,在这种情况下跳过步骤或使用TRUNCATE(如果您没有FK关系)

我做了这个实验,重置值为0,因为我想我的第一个身份列是0,它的工作。

 dbcc CHECKIDENT(MOVIE,RESEED,0) dbcc CHECKIDENT(MOVIE,RESEED,-1) DBCC CHECKIDENT(MOVIE,NORESEED) 
 USE AdventureWorks2012; GO DBCC CHECKIDENT ('Person.AddressType', RESEED, 0); GO AdventureWorks2012=Your databasename Person.AddressType=Your tablename 

我已经在SQL中使用这个设置IDENTITY到一个特定的值: –

 DECLARE @ID int = 42; DECLARE @TABLENAME varchar(50) = 'tablename' DECLARE @SQL nvarchar(1000) = 'IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = '''+@TABLENAME+''' AND last_value IS NOT NULL) BEGIN DBCC CHECKIDENT('+@TABLENAME+', RESEED,' + CONVERT(VARCHAR(10),@ID-1)+'); END ELSE BEGIN DBCC CHECKIDENT('+@TABLENAME+', RESEED,' + CONVERT(VARCHAR(10),@ID)+'); END'; EXEC (@SQL); 

而这在C#中设置了一个特定的值: –

 SetIdentity(context, "tablename", 42); . . private static void SetIdentity(DbContext context, string table,int id) { string str = "IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = '" + table + "' AND last_value IS NOT NULL)\nBEGIN\n"; str += "DBCC CHECKIDENT('" + table + "', RESEED," + (id - 1).ToString() + ");\n"; str += "END\nELSE\nBEGIN\n"; str += "DBCC CHECKIDENT('" + table + "', RESEED," + (id).ToString() + ");\n"; str += "END\n"; context.Database.ExecuteSqlCommand(str); } 

这build立在上面的答案,并始终确保下一个值是42(在这种情况下)。

看起来很荒谬的是,你不能用一个命令来设置/重置一个标识列来覆盖这个表是否有插入logging的情况。 我无法理解我遇到的行为,直到我偶然发现上面的问题! 我的解决scheme – 丑陋但工作 – 是显式检查sys.identity_columns.last_value表,它告诉你表是否有插入logging,并在每种情况下调用适当的DBCC CHECKIDENT命令: DECLARE @last_value INT = CONVERT(INT, (SELECT last_value FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = 'MyTable')); IF @last_value IS NULL BEGIN -- Table newly created and no rows inserted yet; start the IDs off from 1 DBCC CHECKIDENT ('MyTable', RESEED, 1); END ELSE BEGIN -- Table has rows; ensure the IDs continue from the last ID used DECLARE @lastValUsed INT = (SELECT ISNULL(MAX(ID),0) FROM MyTable); DBCC CHECKIDENT ('MyTable', RESEED, @lastValUsed); END DECLARE @last_value INT = CONVERT(INT, (SELECT last_value FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = 'MyTable')); IF @last_value IS NULL BEGIN -- Table newly created and no rows inserted yet; start the IDs off from 1 DBCC CHECKIDENT ('MyTable', RESEED, 1); END ELSE BEGIN -- Table has rows; ensure the IDs continue from the last ID used DECLARE @lastValUsed INT = (SELECT ISNULL(MAX(ID),0) FROM MyTable); DBCC CHECKIDENT ('MyTable', RESEED, @lastValUsed); END