2

「ID」列を持つデータベースがあります。データベースに新しいエントリがある場合は常に、データベースから最後の ID をフェッチし、値を増やしてから、Insert ステートメントで使用します。

EDIT : 複数の Insert ステートメントで使用する ID が必要です。この ID をプライマリ テーブルから取得し、この ID を使用して関連するテーブルに値を挿入します。

    NextID = Select Max(ID) + 1 From Table

    INSERT INTO Table1(ID, Col1, Col2...) Values(NextId, Value1, Value2...)

    INSERT INTO Table2 (ID,col1,col2....) Values (NextID, Value1, Value2...)

並行性の問題があることはわかっているので、これが良い方法かどうかはわかりません。アプリケーションが NextID を読み取ろうとすると、アプリケーションの別のインスタンスも同じ値を読み取ろうとする可能性があるため、同時実行の問題が発生する可能性があります。

この状況に対処する適切な方法はありますか?つまり、データベースの分離レベルを設定する方法があります。この状況に適切な分離レベルはどれでしょう。

また、データベース内の ID を手動で維持およびインクリメントする別の方法を提案できる人がいれば、それも受け入れます。

この情報が十分でない場合は、必要なものをお知らせください。

VB および MS Sql Server 2008 で ASP.Net を使用しています。SQL Server の組み込みの「ID」を使用したくありません。

4

3 に答える 3

3

次の ID を取得する唯一の方法は、実際に行を挿入して ID を使用することです。それ以外はすべて失敗します。したがって、親テーブルに挿入することから始める必要があります。

begin transaction;
insert into Table (col1, col2, col3) values (value1, value2, value3);
set @Id = scope_identity();
insert into Table1(ID, col1, col2) values (@Id, ...);
insert into Table3(ID, col1, col2) values (@Id, ...);
commit;

これはアトミックで同時実行セーフです。

SQL Server の組み込みの「Identity」を使用したくありません。

tl;dr。理由を明確に説明できない限り、あなたが「欲しい」ものはほとんど問題になりません。あなたはそれを正しく行うことができます.

于 2012-11-16T09:38:21.090 に答える
1

基本的に、3つのSQLステートメントのバッチがあります。1つはselect、2つはinsertです。データベースエンジンは、それらの間の任意の場所にある別のセッションから別のステートメントを実行できるため、データの一貫性が失われます。他のセッションは、取得したものと同じMAX()値を取得し、それを他の挿入ステートメントに使用できます。DBエンジンがそれを行わないようにする唯一の方法は、トランザクションを使用することです。バッチをBEGINTRANSACTION... COMMITでラップすると、完了です。

于 2012-11-16T07:12:24.527 に答える
1

これをうまくやる方法、必要なのはトランザクション処理です..

BEGIN TRANSACTION 

begin try
    NextID = Select Max(ID) + 1 From Table

    INSERT INTO Table1(ID, Col1, Col2...) Values(NextId, Value1, Value2...)

    INSERT INTO Table2 (ID,col1,col2....) Values (NextID, Value1, Value2...)

    COMMIT TRANSACTION 
end try

begin catch

    ROLLBACK TRANSACTION 
    --exception logging goes here

end catch
于 2012-11-16T07:35:38.703 に答える