Redefinir AutoIncrement no SQL Server após excluir

266

Excluí alguns registros de uma tabela em um banco de dados do SQL Server. Agora, os IDs vão de 101 a 1200. Quero excluir os registros novamente, mas quero que os IDs voltem para 102. Existe uma maneira de fazer isso no SQL Server?

jumbojs
fonte
46
Por favor, não diga "Não faça". Eu odeio quando pergunto como fazer algo e tudo que recebo é que não. Sim, redefinir a identidade pode causar problemas de chave estrangeira, mas somente se você não conhecer seu banco de dados e programar adequadamente. Existem boas razões para redefinir uma identidade após uma exclusão programada - eles são chamados de Auditores. Os auditores detestam ver as lacunas, preenchê-las, fazê-lo de maneira controlada e garantir que as restrições das chaves estrangeiras sejam mantidas.
6
@ Spyder, você sabia que terá lacunas se uma inserção de registro for revertida não apenas para exclusão? Você não pode evitar lacunas com um incremento automático e é tolice tentar. Eu trabalhei para uma agência de auditoria e os auditores competentes podem explicar isso a eles. Além disso, se você tiver tabelas de auditoria adequadas, elas poderão ver o que aconteceu com esses registros. Ou, se nunca houver lacunas por razões legais (existem alguns casos disso), apenas um desenvolvedor incompetente usaria um incremento automático e os auditores estão chateados com razão.
HLGEM

Respostas:

455

Emita o seguinte comando para replanejar mytable para iniciar em 1:

DBCC CHECKIDENT (mytable, RESEED, 0)

Leia sobre isso nos Livros on-line (ajuda do BOL, SQL). Também tenha cuidado para não ter registros maiores do que a semente que está configurando.

Robert Wagner
fonte
4
... porque os IDs desses registros serão alegremente reutilizados novamente, causando uma má bagunça.
precisa saber é o seguinte
3
Na verdade, para iniciar os IDs em 1, você precisa usar 0: DBCC CHECKIDENT (mytable, RESEED, 0)
Ryan Lundy
7
"DBCC CHECKIDENT (table_name)" define a semente para o mais alto de identidade na tabela, do que você não tem que "ter cuidado"
user1027167
4
@ user1027167 Não, sua resposta não funcionou para mim. Ele continuava incrementando o ID mais alto que havia salvo internamente. Eu tive que usar explicitamente "RESEED, 18" no meu caso para obter "19" como próximo ID. Sem ele, continuava aumentando alegremente em "29".
Matthis Kohli
DBCC CHECKIDENT (table_name) somente altera a semente se o valor da identidade for menor que o valor máximo na coluna. Portanto, se o valor da identidade já for maior como o caso @MatthisKohli, a realocação explícita deverá ser chamada.
Martheen 18/10/16
82
DBCC CHECKIDENT('databasename.dbo.tablename', RESEED, number)

se número = 0, na próxima inserção, o campo de incremento automático conterá o valor 1

se número = 101, na próxima inserção, o campo de incremento automático conterá o valor 102


Algumas informações adicionais ... Pode ser útil para você

Antes de fornecer o incremento automático numberna consulta acima, você deve garantir que a coluna de incremento automático da tabela existente contenha valores menores que isso number.

Para obter o valor máximo de uma coluna (nome_da_coluna) de uma tabela (tabela1), você pode usar a seguinte consulta

 SELECT MAX(column_name) FROM table1
Fathah Rehman P
fonte
37

semi à prova de idiotas:

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

user423430
fonte
1
"DBCC CHECKIDENT (table_name)" faz o mesmo (possível sem condições de corrida)
user1027167
2
@ user1027167 Os documentos dizem 'se o valor atual da identidade de uma tabela for menor que o valor máximo da identidade armazenada na coluna de identidade'; que não cobre a limpeza após a exclusão dos dados (reutilização de IDs - geralmente uma má ideia). Verificado no SQL 2008
user423430
1
A melhor resposta sistemática e automática. Bravo!
Mehdi Khademloo
11

Se você estiver usando o MySQL, tente o seguinte:

ALTER TABLE tablename AUTO_INCREMENT = 1
xaa
fonte
3
Esta é uma resposta para o MySQL. O OP está perguntando sobre o MSSQL.
reformada
a pergunta é sobre MS SQL Server
Saher Ahwal
6

Exclua e recompense todas as tabelas em um banco de dados.

    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.
BMG
fonte
6

Eu descobri. Está:

 DBCC CHECKIDENT ('tablename', RESEED, newseed)
jumbojs
fonte
4

Com base na resposta aceita, para aqueles que encontraram um problema semelhante, com qualificação completa do esquema:

( [MyDataBase].[MySchemaName].[MyTable]) ... resulta em um erro, você precisa estar no contexto desse banco de dados

Ou seja, o seguinte gerará um erro:

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

Coloque o nome completo da tabela com aspas simples:

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

Várias respostas recomendam o uso de uma declaração como esta:

DBCC CHECKIDENT (mytable, RESEED, 0)

Mas o OP disse que "excluiu alguns registros", que podem não ser todos, portanto, um valor de 0 nem sempre é o correto. Outra resposta sugeriu encontrar automaticamente o valor atual máximo e reenviar para esse, mas isso pode causar problemas se não houver registros na tabela e, portanto, max () retornará NULL. Um comentário sugerido usando simplesmente

DBCC CHECKIDENT (mytable)

redefinir o valor, mas outro comentário afirmou corretamente que isso apenas aumenta o valor para o máximo já existente na tabela; isso não reduzirá o valor se ele já for maior que o máximo da tabela, que é o que o OP queria fazer.

Uma solução melhor combina essas idéias. O primeiro CHECKIDENT redefine o valor para 0 e o segundo o redefine para o valor mais alto atualmente na tabela, caso haja registros na tabela:

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

Como vários comentários indicaram, verifique se não há chaves estrangeiras em outras tabelas apontando para os registros excluídos. Caso contrário, essas chaves estrangeiras apontarão para os registros criados após a nova propagação da tabela, o que quase certamente não é o que você tinha em mente.

Michael Rodby
fonte
4

Quero adicionar esta resposta porque a DBCC CHECKIDENTabordagem-produzirá problemas quando você usar esquemas para tabelas. Use isto para ter certeza:

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

Se você deseja verificar o sucesso da operação, use

SELECT IDENT_CURRENT(@Table);

que deve aparecer 0no exemplo acima.

Alexander Schmidt
fonte
1

Você não deseja fazer isso em geral. Reseed pode criar problemas de integridade de dados. É realmente apenas para uso em sistemas de desenvolvimento em que você está limpando todos os dados de teste e iniciando novamente. Ele não deve ser usado em um sistema de produção, caso todos os registros relacionados não tenham sido excluídos (nem todas as tabelas que deveriam estar em um relacionamento de chave estrangeira são!). Você pode criar uma bagunça fazendo isso e, especialmente, se quiser fazê-lo regularmente após cada exclusão. É uma má idéia se preocupar com lacunas nos valores dos campos de identidade.

HLGEM
fonte
6
Eu não vou usá-lo o tempo todo e foi apenas em um teste db.
21449 jumbojs
0

Que tal isso?

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

Essa é uma maneira rápida e simples de alterar o incremento automático para 0 ou o número que você desejar. Eu descobri isso exportando um banco de dados e lendo o código pessoalmente.

Você também pode escrevê-lo assim para torná-lo uma solução de linha única:

ALTER TABLE `table_name` MODIFY `id` int(12) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;
Victor Resnov
fonte
1
Obrigado por este trecho de código, que pode fornecer ajuda imediata e limitada. Uma explicação adequada melhoraria bastante seu valor a longo prazo , mostrando por que essa é uma boa solução para o problema e a tornaria mais útil para futuros leitores com outras perguntas semelhantes. Por favor edite sua resposta para adicionar alguma explicação, incluindo as suposições que você fez.
Adeus StackExchange 5/03/19