1

SQL Server 2008 を使用しています

マイクロソフトによると、http://msdn.microsoft.com/en-us/library/ms188059.aspx

次を実行すると

set identity_insert on  
//insert statements here
set identity_insert off

列の ID は最大値に設定されます。これを避けることはできますか?

次のシナリオを考えてみましょう。

私のテーブルには次のように2行あります

id, name  comm  
1,  John, 232.43  
2,  Alex, 353.52  

上記のコードを使用して、挿入すると

10, Smith, 334.23

上記のリンクに従って、SQL Server は自動的に ID を 10 に設定します。したがって、新しく挿入されたレコード (identity_insert on を使用しない) の場合、ID は自動的に 11 から始まります。

identity_insert on/off を使用した後、ID 値を 3 にしたい

助けてください。

4

4 に答える 4

3

これは、このディスカッションのテスト テーブルです。

create table t4721736 ( id int identity primary key, name varchar(10), comm money )
insert t4721736 select 'John', 232.43 -- id=1
insert t4721736 select 'Alex', 353.52 -- id=2

-- check contents    
select * from t4721736 

-- do all this in a transaction
BEGIN TRAN

-- dummy insert
insert t4721736 select 'dummy', null

-- get what the id should be
declare @resetto bigint
set @resetto = scope_identity()

-- remove dummy record
delete t4721736 where id = @resetto

-- perform the insert(s)
set identity_insert t4721736 on;
insert t4721736(id,name,comm) select 10000000, 'Smith', 334.23;
set identity_insert t4721736 off;

-- reset the identity
set @resetto = @resetto - 1  -- it needs to be 1 prior
DBCC CHECKIDENT(t4721736, RESEED, @resetto)

COMMIT

範囲が指定された ID を持つレコードに達するとすぐに失敗することを完全に理解していると仮定します (そうだと思います)。SQL Server は、既にレコードが添付されている ID に対して自動スキップを実行しません。

これは問題にはなりません。identity_insert を使用して挿入すると、id の値は 1,000 万を超えます。したがって、衝突の問題はありません

これがどのように失敗するかを確認するには、上記のコードで「10000000」を「10」に変更してプロセスをショートカットします。次に、これらをフォローアップします。

-- inspect contents, shows records 1,2,10
select * from t4721736

-- next, insert 7 more records, bringing the id up to 9
insert t4721736 select 'U3', 0
insert t4721736 select 'U4', 0
insert t4721736 select 'U5', 0
insert t4721736 select 'U6', 0
insert t4721736 select 'U7', 0
insert t4721736 select 'U8', 0
insert t4721736 select 'U9', 0

最後に、以下の次の挿入を試してください

insert t4721736 select 'U10', 0
于 2011-01-18T10:13:30.497 に答える
2

挿入するこれらの行が特別な/魔法の行である場合 (そのため、特定の ID が必要です)、これらの行に負の ID 値を持たせることを検討しましたか? そうすれば、競合がなくなり、それらを追加しても IDENTITY 値がリセットされることはありません。

これらの行を非常に異なる ID 値で挿入する必要がある理由が他にある場合は、質問を拡張して、それに関する情報を提供してください。より良い解決策を提供できる可能性があります。

于 2011-01-18T11:32:20.797 に答える
2

次を使用してシード値をリセットできますDBCC CHECKIDENT

DBCC CHECKIDENT ("MyTable", RESEED, 3);
GO

ただし、 10のレコード ID を挿入したため、次のレコードは実際には 11 になります。

コマンドで文書化されています:

テーブルの現在の ID 値が ID 列に格納されている最大 ID 値より小さい場合、ID 列の最大値を使用してリセットされます。

両方の方法を持つことはできません。最低の ID をベース シードの値にするか、そうでないかのいずれかです。

于 2011-01-18T08:13:13.533 に答える
0

「植え付けられたバグ」のジレンマを回避するもう 1 つの方法は、独自の ID ジェネレーター プロシージャと追跡テーブルを作成することです。テーブルには、次の ID となるテーブル名と値が含まれています。このようにして、いつでも任意の値をリセットできます。この手順には、次に生成されたキーが存在するかどうかを確認するロジックが含まれます。存在する場合は、テーブルに存在しない ID が見つかるまでキーをインクリメントし、それをユーザーに返します。これを正しく機能させるには、すべての挿入に実装する必要があります。これはトリガーで可能です。マイナス面は、Damien_The_Unbeliever が示唆するような負の数を使用するよりも処理オーバーヘッドが大きくなります。

于 2011-01-19T05:50:24.850 に答える