削除後にSQL ServerのAutoIncrementをリセットする


266

SQL Serverデータベースのテーブルからいくつかのレコードを削除しました。これで、IDは101から1200になりました。レコードをもう一度削除したいのですが、IDを102に戻したいのですが、SQL Serverでこれを行う方法はありますか?


46
「やめて」と言わないでください。私は何かをする方法を尋ねるときにそれを嫌い、私が得るすべてはそうではありません。はい、IDをリセットすると外部キーの問題が発生する可能性がありますが、データベースとそれに応じたプログラムがわからない場合のみです。スケジュールされた削除後にIDをリセットするのには非常に適切な理由があります。これらは監査者と呼ばれます。監査人はギャップを見つけるのが嫌いなので、ギャップを埋め、管理された方法でそれを実行し、外部キーの制約が確実に維持されるようにします。

6
@spyder、レコードの挿入が削除だけでなくロールバックされるとギャップが生じることをご存知ですか?自動インクリメントでギャップを回避することはできず、試すのはばかげています。私は監査機関で働いてきましたが、有能な監査人はこれを説明することができます。さらに、適切な監査テーブルがあれば、それらのレコードに何が起こったかを確認できます。または、法的な理由でギャップが生じてはならない場合(これにはいくつかのケースがあります)、無能な開発者だけが自動インクリメントを使用し、監査人は正しく動揺します。
HLGEM 2012

回答:


455

次のコマンドを発行して、mytableを1から始まるように再シードします。

DBCC CHECKIDENT (mytable, RESEED, 0)

Books on Line(BOL、SQLヘルプ)でそれについて読んでください。また、設定しているシードよりも高いレコードがないことに注意してください。


4
...これらのレコードのIDが再び喜んで再利用され、ひどい混乱を引き起こすからです。
nalply

3
実際には、1でIDを開始するために、あなたは0を使用する必要があります DBCC CHECKIDENT (mytable, RESEED, 0)
ライアン・ランディ

7
"DBCC CHECKIDENT(table_name)"は、シードを "注意"する必要のない最も高いIDに設定します
user1027167

4
@ user1027167いいえ、あなたの答えはうまくいきませんでした。内部で保存した最高のIDで増加し続けました。私の場合、次のIDとして「19」を取得するには、「RESEED、18」を明示的に使用する必要がありました。それがなければ「29」で楽しく増加し続けました。
Matthis Kohli 2016

DBCC CHECKIDENT(table_name)は、ID値が列の最大値よりも低い場合にのみシードを変更します。したがって、@ MatthisKohliの場合のようにID値がすでに大きい場合は、明示的な再シードを呼び出す必要があります。
Martheen 2016年

82
DBCC CHECKIDENT('databasename.dbo.tablename', RESEED, number)

number = 0の場合、次の挿入で自動インクリメントフィールドには値1が含まれます

number = 101の場合、次の挿入で自動増分フィールドに値102が含まれます


いくつかの追加情報...役に立つかもしれません上記のクエリで

自動インクリメントを行う前にnumber、既存のテーブルの自動インクリメント列にそれより小さい値が含まれていることを確認する必要がありますnumber

table(table1)からcolumn(column_name)の最大値を取得するには、次のクエリを使用できます

 SELECT MAX(column_name) FROM table1

37

半ばか証拠:

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


1
「DBCC CHECKIDENT(table_name)」は同じことを行います(競合状態なしで可能)
user1027167 '19

2
@ user1027167ドキュメントには、「テーブルの現在のID値がID列に格納されている最大ID値よりも小さい場合」と記載されています。これは、データが削除された後のクリーンアップをカバーしません(IDの再利用-多くの場合悪い考えです)。SQL 2008で検証済み
user423430 2014

1
最高の体系的かつ自動的な答え。ブラボー!
Mehdi Khademloo、2015年

11

MySQLを使用している場合は、次のことを試してください。

ALTER TABLE tablename AUTO_INCREMENT = 1

3
これはMySQLの答えです。OPはMSSQLについて質問しています。
2017年

問題はMS SQL Serverに関するものです
Saher Ahwal

6

データベース内のすべてのテーブルを削除して再シードします。

    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.

6

私はそれを考え出した。それは:

 DBCC CHECKIDENT ('tablename', RESEED, newseed)

4

承認された回答に基づいて、完全なスキーマ修飾で同様の問題が発生した場合:

[MyDataBase].[MySchemaName].[MyTable])...エラーが発生します。そのDBのコンテキストにいる必要があります

つまり、以下はエラーをスローします。

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

代わりに、完全修飾テーブル名を単一引用符で囲みます。

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

4

いくつかの回答では、次のようなステートメントの使用を推奨しています。

DBCC CHECKIDENT (mytable, RESEED, 0)

しかし、OPは「一部のレコードを削除しました」と言ったため、すべてではない可能性があるため、値0が常に正しいとは限りません。別の回答では、現在の最大値を自動的に見つけて再シードすることを提案しましたが、テーブルにレコードがない場合に問題が発生し、max()がNULLを返します。単に使用して提案されたコメント

DBCC CHECKIDENT (mytable)

値をリセットしますが、別のコメントでは、これは値をテーブル内の既存の最大値までしか増加しないと正しく述べています。値がテーブルの最大値よりも高い場合、値は減少しません。これは、OPが実行したかったことです。

より良い解決策は、これらのアイデアを組み合わせたものです。テーブルにレコードがある場合、最初のCHECKIDENTは値を0にリセットし、2番目の値は現在テーブルにある最大値にリセットします。

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

複数のコメントが示しているので、削除されたレコードを指す他のテーブルに外部キーがないことを確認してください。それ以外の場合、これらの外部キーは、テーブルを再シードした後に作成したレコードを指します。これは、ほとんどの場合、意図したものではありません。


4

DBCC CHECKIDENTテーブルにスキーマを使用すると-approachが問題を生成するため、この回答を追加したいと思います。これを確認してください:

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

操作の成功を確認したい場合は、

SELECT IDENT_CURRENT(@Table);

0上記の例で出力されるはずです。


1

一般的にはこれを実行する必要はありません。再シードはデータの整合性の問題を引き起こす可能性があります。実際には、すべてのテストデータを消去してやり直す開発システムでのみ使用できます。すべての関連レコードが削除されていない場合に備えて、本番システムでは使用しないでください(外部キー関係にある必要があるすべてのテーブルが削除されているわけではありません)。これを行う混乱を作成できます。削除するたびに定期的に行う場合は特にそうです。IDフィールド値のギャップを心配するのは悪い考えです。


6
私はいつもそれを使うつもりはありません、そしてそれはテストデータベースでのみでした。
jumbojs

0

これはどうですか?

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;

1
このコードスニペットをありがとうございます。このコードスニペットは、制限された即時のヘルプを提供する可能性があります。適切な説明が大幅に長期的な価値を向上させるだろう示すことによって、なぜこれが問題に良い解決策であり、他の、同様の質問を将来の読者にそれがより便利になるだろう。回答を編集して、仮定を含めて説明を追加してください。
さようならStackExchange 2019年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.