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

存在する場合はUPDATE、それ以外の場合はSQLServer2008でINSERT

    多くの人がMERGEの使用を提案します 、しかし私はそれに対してあなたに警告します。デフォルトでは、複数のステートメントを超えて並行性や競合状態からユーザーを保護することはありませんが、他の危険をもたらします:

    • SQLServerのMERGEステートメントには注意が必要です
    • MERGEを使用する場合の回避策
    • SQLServerUPSERTパターンとアンチパターン

    この「より単純な」構文が利用可能であっても、私はこのアプローチを好みます(簡潔にするためにエラー処理は省略されています):

    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    BEGIN TRANSACTION;
    UPDATE dbo.table SET ... WHERE PK = @PK;
    IF @@ROWCOUNT = 0
    BEGIN
      INSERT dbo.table(PK, ...) SELECT @PK, ...;
    END
    COMMIT TRANSACTION;
    

    このUPSERTの詳細 ここでのアプローチ:

    • このUPSERTアンチパターンの使用を中止してください

    多くの人がこの方法を提案します:

    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    BEGIN TRANSACTION;
    IF EXISTS (SELECT 1 FROM dbo.table WHERE PK = @PK)
    BEGIN
      UPDATE ...
    END
    ELSE
    BEGIN
      INSERT ...
    END
    COMMIT TRANSACTION;
    

    ただし、これにより、更新する行を見つけるためにテーブルを2回読み取る必要がある場合があります。最初のサンプルでは、​​行を1回だけ見つける必要があります。 (どちらの場合も、最初の読み取りから行が見つからない場合は、挿入が発生します。)

    他の人はこの方法を提案します:

    BEGIN TRY
      INSERT ...
    END TRY
    BEGIN CATCH
      IF ERROR_NUMBER() = 2627
        UPDATE ...
    END CATCH
    

    ただし、ほとんどすべての挿入が失敗するまれなシナリオを除いて、最初に防止できたはずの例外をSQL Serverにキャッチさせる以外の理由がない場合、これははるかにコストがかかる場合に問題があります。私はここで同じことを証明します:

    • TRY/CATCHに入る前に潜在的な制約違反をチェックする
    • さまざまなエラー処理手法によるパフォーマンスへの影響

    1つのステートメントで何が得られると思うかわかりません。私はあなたが何も得ないと思います。 MERGE は単一のステートメントですが、それでも実際には複数の操作を実行する必要があります-そうではないと思わせる場合でも。




    1. ISNUMERIC('。')が1を返すのはなぜですか?

    2. MicrosoftAccessを必要とする5つのジョブ

    3. OracleSQLの「YYYY」と「RRRR」の違いは何ですか

    4. エラー:列が存在しません