sql >> データベース >  >> RDS >> Sqlserver

条件付き Upsert ストアド プロシージャを実装する方法は?

    次のスクリプトをまとめて、私が過去に使用したこのトリックを証明しました。使用する場合は、目的に合わせて変更する必要があります。コメントは次のとおりです:

    /*
    CREATE TABLE Item
     (
       Title      varchar(255)  not null
      ,Teaser     varchar(255)  not null
      ,ContentId  varchar(30)  not null
      ,RowLocked  bit  not null
    )
    
    
    UPDATE item
     set RowLocked = 1
     where ContentId = 'Test01'
    
    */
    
    
    DECLARE
      @Check varchar(30)
     ,@pContentID varchar(30)
     ,@pTitle varchar(255)
     ,@pTeaser varchar(255)
    
    set @pContentID = 'Test01'
    set @pTitle     = 'TestingTitle'
    set @pTeaser    = 'TestingTeasier'
    
    set @check = null
    
    UPDATE dbo.Item
     set
       @Check = ContentId
      ,Title  = @pTitle
      ,Teaser = @pTeaser
     where ContentID = @pContentID
      and RowLocked = 0
    
    print isnull(@check, '<check is null>')
    
    IF @Check is null
        INSERT dbo.Item (ContentID, Title, Teaser, RowLocked)
         values (@pContentID, @pTitle, @pTeaser, 0)
    
    select * from Item
    

    ここでの秘訣は、Update ステートメント内のローカル変数に値を設定できることです。上記の「フラグ」値は、更新が機能する (つまり、更新基準が満たされる) 場合にのみ設定されます。それ以外の場合は変更されません (ここでは null のままです)。それを確認し、それに応じて処理できます。

    トランザクションとそれをシリアライズ可能にすることに関して、処理方法を提案する前に、トランザクション内にカプセル化する必要があるものについて詳しく知りたい.

    -- 補遺、以下の 2 番目のコメントからのフォローアップ -----------

    Saffron 氏のアイデアは、主キーが外部で定義され、データベースに渡されるため、このルーチンを実装するための徹底的かつ堅実な方法です (つまり、ID 列を使用していません。>

    さらにテストを行いました (列 ContentId に主キー制約を追加し、UPDATE と INSERT をトランザクションでラップし、シリアル化可能なヒントを更新に追加しました)、はい、それで必要なすべてが実行されるはずです。更新が失敗すると、インデックスのその部分に範囲ロックが適用され、列に新しい値を同時に挿入しようとする試みがブロックされます。もちろん、N 個のリクエストが同時に送信された場合、「最初」が行を作成し、行のどこかに「ロック」を設定しない限り、2 番目、3 番目などによってすぐに更新されます。良いトリックです!

    (キー列にインデックスがないと、テーブル全体がロックされることに注意してください。また、範囲ロックにより、新しい値の「両側」の行がロックされる場合があります-または、ロックされない可能性があります。私はしませんでした操作の期間は [?] 1 桁のミリ秒単位である必要があるため、重要ではありません。)



    1. メディアファイルをデータベースに保存するための最良の方法は何ですか?

    2. MySQLでデータベースの変更を聞く

    3. 1か月で21歳になるすべての従業員を取得するにはどうすればよいですか?

    4. C#DataTableに非同期でデータを入力する