基本的に、すべてのテーブルのIdentityIncrementを元の値にリセットする必要があります。ここでいくつかのコードを試しましたが、失敗します。
リンクからの実際のコード:
USE World00_Character
GO
-- Create a cursor to loop through the System Ojects and get each table name
DECLARE TBL_CURSOR CURSOR
-- Declare the SQL Statement to cursor through
FOR ( SELECT Name FROM Sysobjects WHERE Type='U' )
-- Declare the @SQL Variable which will hold our dynamic sql
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = '';
-- Declare the @TblName Variable which will hold the name of the current table
DECLARE @TblName NVARCHAR(MAX);
-- Open the Cursor
OPEN TBL_CURSOR
-- Setup the Fetch While that will loop through our cursor and set @TblName
FETCH NEXT FROM TBL_CURSOR INTO @TblName
-- Do this while we are not at the end of the record set
WHILE (@@FETCH_STATUS <> -1)
BEGIN
-- Appeand this table's select count statement to our sql variable
SET @SQL = @SQL + ' ( SELECT '''+@TblName+''' AS Table_Name,COUNT(*) AS Count FROM '+@TblName+' ) UNION';
-- Delete info
EXEC('DBCC CHECKIDENT ('+@TblName+',RESEED,(SELECT IDENT_SEED('+@TblName+')))');
-- Pull the next record
FETCH NEXT FROM TBL_CURSOR INTO @TblName
-- End the Cursor Loop
END
-- Close and Clean Up the Cursor
CLOSE TBL_CURSOR
DEALLOCATE TBL_CURSOR
-- Since we were adding the UNION at the end of each part, the last query will have
-- an extra UNION. Lets trim it off.
SET @SQL = LEFT(@SQL,LEN(@SQL)-6);
-- Lets do an Order By. You can pick between Count and Table Name by picking which
-- line to execute below.
SET @SQL = @SQL + ' ORDER BY Count';
--SET @SQL = @SQL + ' ORDER BY Table_Name';
-- Now that our Dynamic SQL statement is ready, lets execute it.
EXEC (@SQL);
GO
エラーメッセージ:
Error: Msg 102, Level 15, State 1, Line 1 Incorrect syntax near '('.
そのSQLを修正するか、すべてのテーブルのIDを元にリセットするにはどうすればよいですか?
シードと増分が1でないテーブルがたくさんありますか?
そうでない場合(デフォルトでは、すべてのテーブルにそれがあります)、次のコードを使用します。
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT(''?'', RESEED, 1)'
MSforeachtable
は文書化されていませんが、データベース内のすべてのテーブルに対して特定のコマンドを実行する非常に便利なストアドプロシージャです。
完全に正確にする必要がある場合は、次のステートメントを使用します。SQLステートメントのリストが生成され、すべてのテーブルが元のSEED値に再シードされます。
SELECT
IDENT_SEED(TABLE_NAME) AS Seed,
IDENT_INCR(TABLE_NAME) AS Increment,
IDENT_CURRENT(TABLE_NAME) AS Current_Identity,
TABLE_NAME,
'DBCC CHECKIDENT(' + TABLE_NAME + ', RESEED, ' + CAST(IDENT_SEED(TABLE_NAME) AS VARCHAR(10)) + ')'
FROM
INFORMATION_SCHEMA.TABLES
WHERE
OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 'TableHasIdentity') = 1
AND TABLE_TYPE = 'BASE TABLE'
出力の最後の列を取得し、それらのステートメントを実行すれば完了です。 :-)
( ブログ投稿 PinalDaveに触発されました)
Marc_sの回答を少し調整します。
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'', RESEED)'
?の周りのそれらの一重引用符性格が重要です。このステートメントにより、SQLServerは各テーブルの次のID値を自動的に再計算します。
スキーマを少しうまく処理するわずかなバリエーション...
SELECT
IDENT_SEED(TABLE_SCHEMA+'.'+TABLE_NAME) AS Seed,
IDENT_INCR(TABLE_SCHEMA+'.'+TABLE_NAME) AS Increment,
IDENT_CURRENT(TABLE_SCHEMA+'.'+TABLE_NAME) AS Current_Identity,
TABLE_SCHEMA+'.'+TABLE_NAME,
'DBCC CHECKIDENT('''+TABLE_SCHEMA+'.'+TABLE_NAME+''', RESEED, '+CAST(IDENT_SEED(TABLE_SCHEMA+'.'+TABLE_NAME) AS VARCHAR(10))+')'
FROM
INFORMATION_SCHEMA.TABLES
WHERE
OBJECTPROPERTY(OBJECT_ID(TABLE_SCHEMA+'.'+TABLE_NAME), 'TableHasIdentity') = 1
AND TABLE_TYPE = 'BASE TABLE'
ORDER BY TABLE_SCHEMA, TABLE_NAME
テーブルにデータが含まれている場合は、このコマンドを使用するときに注意してください。すべての新しい挿入で重複エラーが発生します。
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT(''?'', RESEED,1)'
問題を解決するには、その後これを実行する必要があります
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT(''?'', RESEED)'
データが存在する場合、これによりシードが最後の列IDにリセットされます
sp_MSForEachTable
を使用し、テーブルをリセットする前にテーブルにID値があるかどうかを確認する別の方法:
EXEC sp_MSForEachTable '
Print ''?''
IF OBJECTPROPERTY(object_id(''?''), ''TableHasIdentity'') = 1
DBCC CHECKIDENT (''?'', RESEED, 0)
else
Print ''Table does not have an identity value''
'
注:ID値を1から開始する場合、DBCCコマンドはCHECKIDENT (''?'', RESEED, 0)
ではなくCHECKIDENT (''?'', RESEED, 1)
を使用する必要があります。いくつかの回答に示されています。 MS SQL Serverドキュメント からの引用:
次の例では、AddressTypeテーブルのAddressTypeID列の現在のID値を値10に強制します。テーブルには既存の行があるため、次に挿入される行は値として11を使用します。つまり、に対して定義された新しい現在の増分値です。列の値に1を加えたもの
USE AdventureWorks2012;
GO
DBCC CHECKIDENT ('Person.AddressType', RESEED, 10);
GO
ID列を持つテーブルのみを再シードするには、次のスクリプトを使用できます。また、sp_MSforeachtable
を利用しますが、正しいテーブルを考慮に入れます。
EXEC sp_MSforeachtable '
IF (SELECT COUNT(1)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = ''BASE TABLE''
AND ''[''+ TABLE_SCHEMA + ''].['' + TABLE_NAME + '']'' = ''?''
AND OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), ''TableHasIdentity'') = 1) > 0
BEGIN
DBCC CHECKIDENT (''?'', RESEED, 1)
END'
簡単な方法は、sp_MSforeachtableコマンドを使用することです。これは、文書化されていませんが、テーブルを調べる比較的よく知られているコマンドです。
おそらく最も簡単な方法(これは聞こえるほどクレイジーで、見た目はコードの臭いがする)は、次のようにDBCC CHECKIDENT
を2回実行することです。
-- sets all the seeds to 1
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'', RESEED, 1)'
-- run it again to get MSSQL to figure out the MAX/NEXT seed automatically
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'')'
完了。
必要に応じて、もう一度実行して、すべてのシードが何に設定されているかを確認できます。
-- run it again to display what the seeds are now set to
exec sp_MSforeachtable @command1 = 'DBCC CHECKIDENT (''?'')'
これは、ドキュメントからのコメントを活用するための創造的な方法です。
テーブルの現在のID値が、ID列に格納されている最大ID値よりも小さい場合、ID列の最大値を使用してリセットされます。
以下のコードを使用してください。
CREATE TABLE #tmptable
(
[seednvalue] int not null,
[tablename] [nvarchar] (100) NULL
)
declare @seedvalue AS INT
DECLARE @tablename AS VARCHAR(100)
Declare #tablesIdentityCursor CURSOR
for
SELECT
IDENT_CURRENT(TABLE_NAME)+1 AS Current_Identity,
TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 'TableHasIdentity') = 1
AND TABLE_TYPE = 'BASE TABLE' --AND TABLE_NAME='test11'
delete from #tmptable
Open #tablesIdentityCursor
FETCH NEXT FROM #tablesIdentityCursor into @seedvalue, @tablename
WHILE @@FETCH_STATUS = 0 BEGIN
Insert into #tmptable Select @seedvalue , @tablename
DBCC CHECKIDENT (@tablename, reseed, @seedvalue)
FETCH NEXT FROM #tablesIdentityCursor into @seedvalue, @tablename
END
CLOSE #tablesIdentityCursor
DEALLOCATE #tablesIdentityCursor
SELECT * FROM #tmptable
DROP TABLE #tmptable