SQL Serverデータベーステーブルにレコードを挿入しました。テーブルに主キーが定義されていて、自動インクリメントIDシードが「はい」に設定されています。これは主に、SQL Azureでは各テーブルに主キーとIDを定義する必要があるためです。
しかし、テーブルからいくつかのレコードを削除しなければならないので、それらのテーブルのアイデンティティシードは乱され、インデックスカラム(1の増分で自動生成される)は乱されるでしょう。
レコードが削除された後にID列をリセットして列が昇順の番号順になるようにするにはどうすればよいですか。
Identityカラムは、データベース内のどこでも外部キーとしては使用されません。
DBCC CHECKIDENT
managementコマンドはIDカウンタをリセットするために使用されます。コマンド構文は次のとおりです。
DBCC CHECKIDENT (table_name [, { NORESEED | { RESEED [, new_reseed_value ]}}])
[ WITH NO_INFOMSGS ]
例:
DBCC CHECKIDENT ('[TestTable]', RESEED, 0);
GO
Azure SQL Databaseの以前のバージョンではサポートされていませんでしたが、現在はサポートされています。
new_reseed_value
引数はSQL Serverのバージョンによって異なります - ドキュメントによれば :
テーブルに行がある場合は、次の行にnew_reseed_valueという値が挿入されます。 SQL Server 2008 R2以前のバージョンでは、挿入される次の行にnew_reseed_value +現在の増分値が使用されます。
ただし、 この情報は誤解を招く可能性があります (実際には明らかに間違っています)少なくともSQL Server 2012は現在もnew_reseed_value +現在の増分値ロジックを使用していることを示しているマイクロソフトは、同じページにある独自のExample C
と矛盾することさえあります。
C.現在のアイデンティティ値を新しい値に強制する
次の例では、AddressTypeテーブルの AddressTypeID列の現在のID値を強制的に10にします。テーブルには既存の行があるため、挿入される次の行には11 の値、つまり列の値に定義された新しい現在の増分値に1を加えた値。
USE AdventureWorks2012;
GO
DBCC CHECKIDENT ('Person.AddressType', RESEED, 10);
GO
それでも、これはすべて新しいSQL Serverバージョンでは異なる動作のためのオプションを残します。マイクロソフトが独自のドキュメントで整理するまで、使用する前に実際のテストを行うことが唯一の確実な方法です。
DBCC CHECKIDENT ('TestTable', RESEED, 0)
GO
0はidentity
の開始値です。
IF all がデータからDELETE
を介してテーブルから削除されている(つまり、WHERE
句がない)こと、そしてa)許可が許す限りb)FKがないことに注意してください。 TRUNCATE TABLE
を使用すると(より効率的なDELETE
と を使用してIDENTITY
シードを同時にリセットするため)テーブルを参照する(ここではそうであると思われる)のが好ましいでしょう。以下の詳細は、 TRUNCATE TABLE のMSDNページから引用されています。
DELETEステートメントと比較して、TRUNCATE TABLEには以下の利点があります。
使用されるトランザクションログスペースが少なくなります。
DELETEステートメントは、一度に1行ずつ行を削除し、削除された行ごとにエントリをトランザクションログに記録します。 TRUNCATE TABLEは、テーブルデータの格納に使用されているデータページの割り当てを解除することでデータを削除し、ページ割り当て解除のみをトランザクションログに記録します。
通常使用されるロックは少なくなります。
行ロックを使用してDELETE文を実行すると、テーブル内の各行が削除のためにロックされます。 TRUNCATE TABLEは常にテーブル(スキーマ(SCH-M)ロックを含む)とページをロックしますが、各行はロックしません。
例外なく、ゼロページはテーブルに残ります。
DELETEステートメントが実行された後、テーブルはまだ空のページを含むことができます。たとえば、ヒープ内の空のページは、少なくとも排他的(LCK_M_X)テーブルロックがないと割り当て解除できません。削除操作がテーブルロックを使用しない場合、テーブル(ヒープ)には空のページが多数含まれます。インデックスの場合、削除操作によって空のページが残ることがありますが、これらのページはバックグラウンドクリーンアッププロセスによって迅速に割り当て解除されます。
テーブルにID列が含まれている場合、その列のカウンターはその列に定義されているシード値にリセットされます。シードが定義されていない場合は、デフォルト値1が使用されます。 IDカウンタを保持するには、代わりにDELETEを使用してください。
だから、以下:
DELETE FROM [MyTable];
DBCC CHECKIDENT ('[MyTable]', RESEED, 0);
ちょうどになります:
TRUNCATE TABLE [MyTable];
制限事項などの追加情報についてはTRUNCATE TABLE
のドキュメント(上記リンク)をご覧ください。
ほとんどの回答はRESEEDを0にすることを示唆していますが、利用可能な次のIdに再シードするだけでよい
declare @max int
select @max=max([Id])from [TestTable]
if @max IS NULL //check when max is returned as null
SET @max = 0
DBCC CHECKIDENT ('[TestTable]', RESEED,@max)
これによりテーブルがチェックされ、次のIDにリセットされます。
私は@anil shahs
答えを試みました、そしてそれはアイデンティティをリセットしました。しかし、新しい行が挿入されたとき、それはidentity = 2
を取得しました。その代わりに、構文を次のように変更しました。
DELETE FROM [TestTable]
DBCC CHECKIDENT ('[TestTable]', RESEED, 0)
GO
その後、最初の行はidentity = 1になります。
ほとんどの回答はRESEED
から0
を提案していますが、これをTRUNCATED
テーブルの欠陥と見なしている人もいますが、MicrosoftはID
を除外する解決策を持っています
DBCC CHECKIDENT ('[TestTable]', RESEED)
これによりテーブルがチェックされ、次のID
にリセットされます。これはMS SQL 2005から現在まで利用可能です。
@jacob
DBCC CHECKIDENT ('[TestTable]', RESEED,0)
DBCC CHECKIDENT ('[TestTable]', RESEED)
私のために働きました、私はちょうどテーブルから最初にすべてのエントリーをクリアしなければなりませんでした、そして次に削除の後にトリガーポイントで上記を加えました。今私はエントリを削除するたびにそこから取得されます。
ID列を新しいIDでリセットします...
DECLARE @MAX INT
SELECT @MAX=ISNULL(MAX(Id),0) FROM [TestTable]
DBCC CHECKIDENT ('[TestTable]', RESEED,@MAX)
2コマンドを発行するとトリックを行うことができます
DBCC CHECKIDENT ('[TestTable]', RESEED,0)
DBCC CHECKIDENT ('[TestTable]', RESEED)
最初のものはアイデンティティをゼロにリセットし、次のものは次の利用可能な値に設定します
これはよくある質問であり、答えは常に同じです。それをしないでください。アイデンティティ値は任意のものとして扱われるべきであり、「正しい」順序はありません。
Truncate
テーブルは、レコードをクリアし、カウンターをリセットし、そしてディススペースを取り戻すので、好ましいです。
Delete
およびCheckIdent
は、外部キーによって切り捨てられない場合にのみ使用してください。
このスクリプトを実行してID列をリセットします。 2つの変更を加える必要があります。 tableXYZを更新する必要のあるテーブルに置き換えます。また、ID列の名前を一時テーブルから削除する必要があります。これは、35,000行3列のテーブルでは瞬間的でした。明らかに、テーブルをバックアップして、まずテスト環境でこれを試してください。
select *
into #temp
From tableXYZ
set identity_insert tableXYZ ON
truncate table tableXYZ
alter table #temp drop column (nameOfIdentityColumn)
set identity_insert tableXYZ OFF
insert into tableXYZ
select * from #temp
このストアドプロシージャを使用してください。
IF (object_id('[dbo].[pResetIdentityField]') IS NULL)
BEGIN
EXEC('CREATE PROCEDURE [dbo].[pResetIdentityField] AS SELECT 1 FROM DUMMY');
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[pResetIdentityField]
@pSchemaName NVARCHAR(1000)
, @pTableName NVARCHAR(1000) AS
DECLARE @max INT;
DECLARE @fullTableName NVARCHAR(2000) = @pSchemaName + '.' + @pTableName;
DECLARE @identityColumn NVARCHAR(1000);
SELECT @identityColumn = c.[name]
FROM sys.tables t
INNER JOIN sys.schemas s ON t.[schema_id] = s.[schema_id]
INNER JOIN sys.columns c ON c.[object_id] = t.[object_id]
WHERE c.is_identity = 1
AND t.name = @pTableName
AND s.[name] = @pSchemaName
IF @identityColumn IS NULL
BEGIN
RAISERROR(
'One of the following is true: 1. the table you specified doesn''t have an identity field, 2. you specified an invalid schema, 3. you specified an invalid table'
, 16
, 1);
RETURN;
END;
DECLARE @sqlString NVARCHAR(MAX) = N'SELECT @maxOut = max(' + @identityColumn + ') FROM ' + @fullTableName;
EXECUTE sp_executesql @stmt = @sqlString, @params = N'@maxOut int OUTPUT', @maxOut = @max OUTPUT
IF @max IS NULL
SET @max = 0
print(@max)
DBCC CHECKIDENT (@fullTableName, RESEED, @max)
go
--exec pResetIdentityField 'dbo', 'Table'
私の答えをもう一度見てください。私はあなたが知っておくべきであることをSQL Server 2008 R2で奇妙な行動に遭遇しました。
drop table test01
create table test01 (Id int identity(1,1), descr nvarchar(10))
execute pResetIdentityField 'dbo', 'test01'
insert into test01 (descr) values('Item 1')
select * from test01
delete from test01
execute pResetIdentityField 'dbo', 'test01'
insert into test01 (descr) values('Item 1')
select * from test01
最初の選択は0, Item 1
を生成します。
2番目のものは1, Item 1
を生成します。テーブルが作成された直後にリセットを実行すると、次の値は0になります。正直なところ、Microsoftがこれを正しく行えないのは当然のことです。これは、テーブルを再作成した後や、テーブルがすでに作成されているときに実行することがある参照テーブルを作成するスクリプトファイルがあるためです。
テーブル全体をクリーンアップしない限り、0に再シードすることはあまり実用的ではありません。
そうでなければ、アンソニー・レイモンドの答えは完璧です。 ID列の最大値を最初に取得してから、最大値をシードします。
完全なDELETE行とIDENTITYカウントをリセットするには、これを使用します(SQL Server 2008 R2)。
USE mydb
-- ##################################################################################################################
-- DANGEROUS!!!! USE WITH CARE
-- ##################################################################################################################
DECLARE
db_cursor CURSOR FOR
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND TABLE_CATALOG = 'mydb'
DECLARE @tblname VARCHAR(50)
SET @tblname = ''
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @tblname
WHILE @@FETCH_STATUS = 0
BEGIN
IF CHARINDEX('mycommonwordforalltablesIwanttodothisto', @tblname) > 0
BEGIN
EXEC('DELETE FROM ' + @tblname)
DBCC CHECKIDENT (@tblname, RESEED, 0)
END
FETCH NEXT FROM db_cursor INTO @tblname
END
CLOSE db_cursor
DEALLOCATE db_cursor
GO
これを行うには、次のスクリプトを使用します。テーブルからすべての行を削除し、現在IDENT_CURRENT
が1に設定されている場合、つまり最初はテーブルに1行しかない場合、 "エラー"が発生するシナリオは1つだけです。
DECLARE @maxID int = (SELECT MAX(ID) FROM dbo.Tbl)
;
IF @maxID IS NULL
IF (SELECT IDENT_CURRENT('dbo.Tbl')) > 1
DBCC CHECKIDENT ('dbo.Tbl', RESEED, 0)
ELSE
DBCC CHECKIDENT ('dbo.Tbl', RESEED, 1)
;
ELSE
DBCC CHECKIDENT ('dbo.Tbl', RESEED, @maxID)
;
DBCC CHECKIDENT (<TableName>, reseed, 0)
これにより、現在の識別値が0に設定されます。
次の値を挿入すると、identity値は1に増加します。