DBCC CHECKIDENT将标识设置为0

时间:2009-01-23 11:17:30

标签: sql sql-server

我正在使用此代码重置表格上的标识:

DBCC CHECKIDENT('TableName', RESEED, 0)

这在大多数情况下工作正常,第一个插入我在Id列中插入1。但是,如果我删除数据库并重新创建它(使用我编写的脚本)然后调用DBCC CHECKIDENT,则插入的第一个项目的ID将为0。

有什么想法吗?

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

10 个答案:

答案 0 :(得分:57)

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

运行DBCC CHECKIDENT('TableName', RESEED, 0)后:
- 新创建的表格将以身份0开头 - 现有表将继续使用标识1

解决方案在下面的脚本中,它有点像一个穷人 - 截断:)

-- 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);

答案 1 :(得分:22)

正如你在问题中指出的那样,它是documented behavior。我仍觉得很奇怪。我用来重新填充测试数据库,即使我不依赖于身份字段的值,在第一次从头开始填充数据库时以及在删除所有数据并再次填充之后,有一些令人讨厌的问题。 / p>

一种可能的解决方案是使用 truncate 来清理表而不是删除。但是之后你需要删除所有约束并在之后重新创建它们

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

,它都是相同的

答案 2 :(得分:4)

将声明更改为

  DBCC CHECKIDENT('TableName', RESEED, 1)

这将从2开始(或重新创建表时为1),但它永远不会为0.

答案 3 :(得分:3)

我这样做是为了将值重置为0,因为我希望我的第一个标识列为0并且它正在工作。

dbcc CHECKIDENT(MOVIE,RESEED,0)
dbcc CHECKIDENT(MOVIE,RESEED,-1)
DBCC CHECKIDENT(MOVIE,NORESEED)

答案 4 :(得分:2)

使用单个命令设置/重置标识列以涵盖表是否已插入记录的情况,这似乎很荒谬。在我偶然发现这个问题之前,我无法理解我所经历的行为!

我的解决方案(丑陋但有效)是显式检查sys.identity_columns.last_value表(它告诉您表是否已插入记录)并在每种情况下调用相应的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

答案 5 :(得分:1)

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

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

答案 6 :(得分:1)

我在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);
}

这建立在上述答案的基础上,并始终确保下一个值为42(在这种情况下)。

答案 7 :(得分:0)

只需执行以下操作:

IF EXISTS (SELECT * FROM tablename)
BEGIN
    DELETE from  tablename
    DBCC checkident ('tablename', reseed, 0)
END

答案 8 :(得分:0)

借用Zyphrax的答案...

go.Surface(z=data1, colorscale="viridis", cmin=-0.15, cmax=0.15)

注意事项: 它旨在用于使用枚举类型定义表初始化数据库的参考数据填充情况,其中这些表中的ID值必须始终从1开始。第一次创建数据库时(例如,在SSDT-DB发布期间) )@Reseed必须为0,但是在重置数据(即删除数据并重新插入数据)时,@ Reseed必须为1。因此,该代码旨在用于存储过程中以重置DB数据,可以将其称为手动,但也可以从SSDT-DB项目中的部署后脚本中调用。这样,参考数据插入仅在一个位置定义,而不仅限于在发布过程中仅在部署后使用,还可以通过调用存储的存储来用于后续使用(以支持开发和自动化测试等)。将数据库重置回已知良好状态的过程。

答案 9 :(得分:-1)

USE AdventureWorks2012;  
GO  
DBCC CHECKIDENT ('Person.AddressType', RESEED, 0);  
GO 



AdventureWorks2012=Your databasename
Person.AddressType=Your tablename