ChatGPT解决这个技术问题 Extra ChatGPT

删除后在 SQL Server 中重置 AutoIncrement

我已经从 SQL Server 数据库的表中删除了一些记录。

表中的 ID 如下所示:

99 100 101 1200 1201...

我想删除后面的记录(ID > 1200),然后我想重置自动增量,以便下一个自动生成的 ID 为 102。所以我的记录是连续的,有没有办法在 SQL Server 中做到这一点?

请不要说“不要这样做”。当我问如何做某事而我得到的只是不做时,我讨厌它。是的,重置身份可能会导致外键问题,但前提是您不知道相应的数据库和程序。在计划删除后重置身份有很好的理由——他们被称为审计员。审计员讨厌看到空白,所以要填补空白,以可控的方式进行,并确保保持外键约束。
@spyder,您是否知道如果回滚记录插入而不仅仅是删除,您将有间隙?您无法通过自动增量避免间隙,尝试是愚蠢的。我曾在一家审计机构工作过,称职的审计员可以向他们解释这一点。此外,如果您有适当的审计表,他们可以看到这些记录发生了什么。或者,如果出于法律原因必须不存在任何漏洞(这种情况很少见),那么只有不称职的开发人员才会使用自动增量,而审计人员会感到不安。

R
Ryan Lundy

发出以下命令以重新设置 mytable 以从 1 开始:

DBCC CHECKIDENT (mytable, RESEED, 0)

在在线书籍(BOL、SQL 帮助)中阅读有关它的信息。另请注意,您的记录不要高于您设置的种子。


...因为这些记录的 id 会很高兴地再次被重用,造成一团糟。
实际上,为了从 1 开始 ID,您需要使用 0:DBCC CHECKIDENT (mytable, RESEED, 0)
“DBCC CHECKIDENT (table_name)”将种子设置为表中的最高标识,而不是您不必“小心”
@user1027167 不,您的回答对我不起作用。它在内部保存的最高 ID 上不断增加。在我的情况下,我必须明确使用“RESEED,18”才能获得“19”作为下一个 ID。没有它,它会在“29”上愉快地递增。
DBCC CHECKIDENT (table_name) 仅当标识值低于列中的最大值时才更改种子。因此,如果身份值已经像@MatthisKohli 的情况一样大,则必须调用显式重新种子。
c
chancrovsky
DBCC CHECKIDENT('databasename.dbo.tablename', RESEED, number)

如果 number=0 则在下一次插入中,自动增量字段将包含值 1

如果 number=101 那么在下一次插入中,自动增量字段将包含值 102

一些附加信息...可能对您有用

在上述查询中给出自动增量 number 之前,您必须确保现有表的自动增量列包含的值小于number

要从表(table1)中获取列(column_name)的最大值,可以使用以下查询

 SELECT MAX(column_name) FROM table1

你不能不包括种子号,它会使用最大值吗?例如 DBCC CHECKIDENT('databasename.dbo.tablename') 并且 NOT 是否包含 , RESEED, number
u
user423430

半白痴:

declare @max int;  
select @max = max(key) from table;  
dbcc checkident(table,reseed,@max)

http://sqlserverplanet.com/tsql/using-dbcc-checkident-to-reseed-a-table-after-delete


"DBCC CHECKIDENT (table_name)" 也一样(可能没有竞争条件)
@user1027167 文档说“如果表的当前标识值小于存储在标识列中的最大标识值”;这不包括删除数据后的清理(重新使用 id - 通常是一个坏主意)。在 SQL 2008 上验证
最好的系统和自动答案。太棒了!
s
shaahiin

如果您使用的是 MySQL,请尝试以下操作:

ALTER TABLE tablename AUTO_INCREMENT = 1

这是 MySQL 的答案。 OP 正在询问 MSSQL。
可能,但答案仍然可以帮助像我这样的其他人。
s
shA.t

我想到了。它的:

 DBCC CHECKIDENT ('tablename', RESEED, newseed)

以及如何获得“新闻种子”?不是我不知道,只是一个完整的答案可以解释这一点。
B
BMG

删除并重新设置数据库中的所有表。

    USE [DatabaseName]
    EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"       -- Disable All the constraints
    EXEC sp_MSForEachTable "DELETE FROM ?"    -- Delete All the Table data
    Exec sp_MSforeachtable 'DBCC CHECKIDENT(''?'', RESEED, 0)' -- Reseed All the table to 0
    Exec sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"  -- Enable All  the constraints back

-- You may ignore the errors that shows the table without Auto increment field.

t
tinonetic

根据接受的答案,对于那些遇到类似问题且具有完整架构资格的人:

([MyDataBase].[MySchemaName].[MyTable])... 导致错误,您需要在该数据库的上下文中

也就是说,以下将引发错误:

DBCC CHECKIDENT ([MyDataBase].[MySchemaName].[MyTable], RESEED, 0)

用单引号将完全限定的表名括起来:

DBCC CHECKIDENT ('[MyDataBase].[MySchemaName].[MyTable]', RESEED, 0)

M
Michael Rodby

几个答案建议使用类似这样的语句:

DBCC CHECKIDENT (mytable, RESEED, 0)

但是 OP 说“删除了一些记录”,这可能不是全部,所以值 0 并不总是正确的。另一个答案建议自动找到最大当前值并重新设置该值,但如果表中没有记录,则会遇到麻烦,因此 max() 将返回 NULL。建议使用简单的评论

DBCC CHECKIDENT (mytable)

重置该值,但另一条评论正确地指出,这只会将值增加到表中已有的最大值;如果它已经高于表中的最大值,这不会减少值,这是 OP 想要做的。

一个更好的解决方案结合了这些想法。第一个 CHECKIDENT 将值重置为 0,第二个将其重置为表中当前的最大值,以防表中有记录:

DBCC CHECKIDENT (mytable, RESEED, 0)
DBCC CHECKIDENT (mytable)

正如多条评论所指出的,确保其他表中没有指向已删除记录的外键。否则,这些外键将指向您在重新设置表后创建的记录,这几乎肯定不是您的想法。


第二个命令需要是 DBCC CHECKIDENT (mytable, RESEED)
@statler 根据 docs.microsoft.com/en-us/sql/t-sql/database-console-commands/… 命令“DBCC CHECKIDENT (table_name)”和“DBCC CHECKIDENT (table_name, RESEED)”做同样的事情。请参阅备注部分中的第二个条目。
显然,但不幸的是,如果您在数据库上运行没有 RESEED 的命令,它将不起作用。无法解释文档。只是。 - 至少在我使用的数据库上。
A
Alexander Schmidt

我想添加此答案,因为当您将架构用于表时,DBCC CHECKIDENT-方法会产生问题。使用它来确保:

DECLARE @Table AS NVARCHAR(500) = 'myschema.mytable';
DBCC CHECKIDENT (@Table, RESEED, 0);

如果要检查操作是否成功,请使用

SELECT IDENT_CURRENT(@Table);

在上面的示例中应该输出 0


H
HLGEM

您一般不希望这样做。 Reseed 会造成数据完整性问题。它实际上仅适用于您要清除所有测试数据并重新开始的开发系统。如果尚未删除所有相关记录,则不应在生产系统上使用它(并非每个应具有外键关系的表!)。这样做可能会造成混乱,特别是如果您打算在每次删除后定期执行此操作。担心身份字段值的差距是个坏主意。


我不会一直使用它,它只是在测试数据库上。
V
Victor Resnov

那这个呢?

ALTER TABLE `table_name`
  MODIFY `id` int(12) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;

这是将自动增量更改为 0 或您想要的任何数字的快速简单的方法。我通过导出数据库并自己阅读代码来解决这个问题。

您也可以这样编写它以使其成为单行解决方案:

ALTER TABLE `table_name` MODIFY `id` int(12) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;

感谢您提供此代码片段,它可能会提供一些有限的即时帮助。 proper explanation would greatly improve its long-term value 通过显示为什么这是解决问题的好方法,并且会使其对有其他类似问题的未来读者更有用。请edit您的回答以添加一些解释,包括您所做的假设。
s
statler

要将数据库中的每个键重置为从最后一个最高键的最大值自动递增:

Exec sp_MSforeachtable 'DBCC CHECKIDENT(''?'', RESEED, 0)'

Exec sp_MSforeachtable 'DBCC CHECKIDENT(''?'', RESEED)'

这是一种在所有表上调用 DBCC 命令的巧妙方法。不幸的是,在没有指定种子值的情况下,CHECKINDENT 命令对我没有任何作用,只是确定了最大值。 @user423430 仍然是为我恢复丢失的身份值的唯一答案。如果我能执行那整套命令,那就太好了。我试过了,但存储过程似乎不接受多个命令。
Y
Yashaswini Bhat

如果您只想重置主键/序列以在 SQL 服务器中以您想要的序列开头,这里是解决方案 -

标识:

99 100 101 1200 1201...

删除 ID >= 1200 的行。(如果您有与这些相关的外键约束,必须处理或删除这些约束才能删除它。)现在您要确保您知道 MAX ID 为当然:

将@max_id 声明为 int = (SELECT MAX(your_column_name) FROM your_table)+1;

(注:+1 表示最大值后的 ID 序列)

重新启动您的序列:

exec('alter sequence your_column_name restart with ' + @max_id);

(注意:with 后面的空格是必须的) 现在新记录将以 102 作为 ID 开头。


J
Joseph Ali

我知道这是一个老问题。但是,我正在为 MySQL 寻找类似的解决方案,并且出现了这个问题。

对于那些正在寻找 MySQL 解决方案的人,您需要运行以下查询:

// important!!! You cannot reset the counter to a value less than or equal to the value that is currently in use. For both InnoDB and MyISAM, if the value is less than or equal to the maximum value currently in the AUTO_INCREMENT column, the value is reset to the current maximum AUTO_INCREMENT column value plus one.
   
ALTER TABLE <your-table-name> AUTO_INCREMENT = 100

documentation