は、私はあなたの基本的なUPSERT機能を実装しようとしているが、ひねりを加えた:時々、私は実際には、既存の行を更新する必要はありません。条件付きUpsertストアドプロシージャを実装する方法は?
基本的に私は、異なるリポジトリの間にいくつかのデータを同期しようとしている、とアップサート機能は、移動するための方法のように思えました。だから、主にSam Saffron's answer to this question、だけでなく、いくつかの他の研究や読書に基づいて、私はこのストアドプロシージャを思い付いた:
(注:私は、MS SQL Server 2005を使用していますので、MERGE文がオプションではありません)
CREATE PROCEDURE [dbo].[usp_UpsertItem]
-- Add the parameters for the stored procedure here
@pContentID varchar(30) = null,
@pTitle varchar(255) = null,
@pTeaser varchar(255) = null
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
BEGIN TRANSACTION
UPDATE dbo.Item WITH (SERIALIZABLE)
SET Title = @pTitle,
Teaser = @pTeaser
WHERE ContentID = @pContentID
IF @@rowcount = 0
INSERT INTO dbo.Item (ContentID, Title, Teaser)
VALUES (@pContentID, @pTitle, @pTeaser)
COMMIT TRANSACTION
END
私は基本的なUpsertについてこれに満足していますが、実際の更新を別の列の値で条件付きにしたいと考えています。 Upsertプロシージャによってそれ以上の更新が行われないように行を「ロック」すると考えてください。私はそうのようなUPDATEステートメントを変更することができます:
UPDATE dbo.Item WITH (SERIALIZABLE)
SET Title = @pTitle,
Teaser = @pTeaser
WHERE ContentID = @pContentID
AND RowLocked = false
しかし、それはすでに存在している行を挿入しようとしますが、ので、更新されなかったとき、その後の挿入は、(コンテンツIDフィールドの)ユニーク制約違反で失敗しますそれは "ロックされていた"。
だから、これは私が行にそれを更新または挿入することができるかどうかを判断するためにあらゆる時間を選択する必要がありますこと、すなわち、私はもはや古典アップサートを持っていることを意味しないのでしょうか?私はそれはケースだ賭けているので、私は、私は本当に手順が安全に実行されるようにトランザクション分離レベル正しいヘルプのであるために求めているものを推測します。あなたが更新の順序を切り替えることができ
RowLocked(AND RowLocked = false)とは何ですか?それはあなたのテーブルの列ですか? –
@AlexKuznetsov - はい、RowLockedはテーブルの列になっています。実際には、行を「ロック」(つまりこの手順では更新しない)にするかどうかを指定する列が2つありますが、SQLを簡略化して質問を明確にしています。しかし、文法はちょっとうんざりしています。もちろん、 "AND RowLocked = 0"でなければなりません。 – Matt