web-dev-qa-db-ja.com

DBCC CHECKIDENT RESEED-新しい値が必要ですか?

再シードについて読んだすべてのドキュメントは、次のようなことを示唆しています。

  1. SET @maxIdentityValue = (SELECT MAX(id) FROM tablename)
  2. DBCC CHECKIDENT('tablename', RESEED, @maxIdentityValue)を実行します

そしてまだ必要なのは単純なDBCC CHECKIDENT('tablename', RESEED)だけであり、最大値を指定しなくても、テーブルから正しいID値を自動的に決定するように見えます。

最初にMAXを使用して値を抽出することが好ましい理由(パフォーマンスまたはその他)はありますか?

ピギーバックの質問:再シードが必要な理由は、レプリケーションを使用していて、データベースレプリケーションが実行されるたびにIDがNullに設定され続けるためです。私は何が間違っているのですか?各テーブルの正しいIDシードを維持するにはどうすればよいですか?

更新(現在の解決策)

今のところ、最大値は使用していません。これは私が使用しているストアドプロシージャです(sys.columnsのクエリを使用して生成し、それぞれを切り取って新しいクエリウィンドウに貼り付けます。厄介で、遅く、エレガントではありませんが、あまり詳しくありません。ストアドプロシージャであり、動的SQLクエリを使用したくない):

declare @seedval integer
declare @maxval integer
declare @newval integer
set @seedval = (select ident_current('mytable'));
set @maxval = (select MAX(id) from mytable);
if @maxval > @seedval or @seedval is NULL
BEGIN
    print 'Need to reseed: max is '  + cast(@maxval as varchar) + ' and seed is ' + cast(@seedval as varchar) 
    dbcc checkident('mytable', RESEED);
    set @newval = (select ident_current('mytable'));
    print 'Max is ' + cast(@maxval as varchar) + ' and seed is ' + cast(@newval as varchar) 
END 
ELSE
    print 'No need to reseed'; 
7
Jordan Reiter

[〜#〜] msdn [〜#〜] で説明されているように、次のように使用するだけで十分です。

 DBCC CHECKIDENT('tablename', RESEED)  

ただし、ほとんどの場合、機能しない次の2つの条件があります。

  • 現在のID値は、テーブルの最大値よりも大きくなっています。
  • すべての行がテーブルから削除されます。

あなたが言及した方法で彼らと一緒に行かなければならない(max(id)と残りを選択する)ので、なぜそもそもわざわざするのですか? :)

9
mohas

再シードしてギャップを残すことができるように、最大​​値を決定したい場合があります(例:最大値+ 100)。 1つのケースは、テーブルの複数のコピーがあり、それらから独立しているが相互に排他的なID範囲を配布しようとしている場合です。

しかし、それでも、パラメーターなしのRESEEDがすべてのシナリオで正しく機能するかどうかはわかりません。

テーブルを最大に再シードするのはよくあることですか?どうして?ループ内に一連の行を生成し、最終的にロールバックする、コーディングが不十分なアプリケーションですか?

いずれの場合も、MAXとRESEEDをトランザクションでラップして、最大値を取得した後、再シードを発行する前にユーザーが新しい行を挿入する可能性を防ぐ必要があります。

2
Aaron Bertrand

(私はこの他の人から私の答えを再投稿していますSOページ)

おそらく最も簡単な方法(これは聞こえるほどクレイジーで、見た目はコードの臭いがする)は、次のように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列の最大値を使用してリセットされます。

1
010110110101