レガシー データベースのテーブルにいくつかのレコードを挿入する必要がありますが、他の古いシステムで使用されているため、テーブルを変更することは解決策ではありません。
問題は、ターゲット テーブルに int 主キーがあるが ID 仕様がないことです。そのため、次に利用可能な ID を見つけて使用する必要があります。
select @id=ISNULL(max(recid)+1,1) from subscriber
ただし、問題が発生しないように、これを行っているときに他のアプリケーションがテーブルに挿入されないようにしたいと考えています。私はこれを試しました:
begin transaction
declare @id as int
select @id=ISNULL(max(recid)+1,1) from subscriber WITH (HOLDLOCK, TABLOCK)
select @id
WAITFOR DELAY '00:00:01'
insert into subscriber (recid) values (@id)
commit transaction
select * from subscriber
SQL Management Studio の 2 つの異なるウィンドウで、1 つのトランザクションが常にデッドロックの犠牲者として強制終了されます。
私もSET TRANSACTION ISOLATION LEVEL SERIALIZABLE
最初に試してみましたが、同じ結果でした...
次のIDを確実に取得して、他の誰か(または私!)が夢中になる危険を冒さずにそれを使用する方法についての良い提案はありますか?
これについて先に言及せずに申し訳ありませんが、これは SQL 2000 サーバーであるため、FOR UPDATE や OUTPUT などは使用できません。
更新:これは私のために働いた解決策です:
BEGIN TRANSACTION
DECLARE @id int
SELECT @id=recid
FROM identities WITH (UPDLOCK, ROWLOCK)
WHERE table_name = 'subscriber'
waitfor delay '00:00:06'
INSERT INTO subscriber (recid) values (@id)
UPDATE identities SET recid=recid+1
WHERE table_name = 'subscriber'
COMMIT transaction
select * from subscriber
WAITFOR は、複数の接続を持ち、クエリを数回開始して同時実行を引き起こすためのものです。
回答してくれた Quassnoi と、貢献してくれた他のすべての人に感謝します! 素晴らしい!