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

1つの状況を除いて、テーブルの更新を防ぐ方法

    INSTEAD OFを使用してみませんか 引き金?もう少し作業が必要です(つまり、UPDATEを繰り返す必要があります 声明)しかし、あなたが仕事を防ぐことができるときはいつでも、それを起こさせてからそれをロールバックする代わりに、あなたはより良くなるでしょう。

    CREATE TRIGGER [dbo].[Item_BeforeUpdate_AnyBilled]
    ON [dbo].[Item]
    INSTEAD OF UPDATE
    AS 
    BEGIN
      SET NOCOUNT ON;
    
      IF EXISTS 
      (
         SELECT 1 FROM inserted i
           JOIN deleted AS d ON i.ItemId = d.ItemId
           WHERE d.BillId IS NULL -- it was NULL before, may not be NULL now
      )
      BEGIN
         UPDATE src 
           SET col1 = i.col1 --, ... other columns
              ModifiedDate = CURRENT_TIMESTAMP -- this eliminates need for other trigger
           FROM dbo.Item AS src
           INNER JOIN inserted AS i
           ON i.ItemId = src.ItemId
           AND (criteria to determine if at least one column has changed);
      END
      ELSE
      BEGIN
         RAISERROR(...);
      END
    END
    GO
    

    これは完全には適合しません。私が省略した基準は、次の理由で省略されています。データ型、列をNULLにできるかどうかなどに依存するため、列の値が変更されたかどうかを判断するのは複雑になる可能性があります。組み込みのトリガー関数を確認してください。特定の列が指定されたかどうかのみがわかり、値が実際に以前から変更されたかどうかはわかりません。

    編集 アフタートリガーによって更新される他の列のみを考慮していることを考えると、次のINSTEAD OF トリガーは、既存の両方のトリガーを置き換えることができ、一度に更新された複数の行を処理することもできます(基準を満たさないものもあります):

    CREATE TRIGGER [dbo].[Item_BeforeUpdate_AnyBilled]
    ON [dbo].[Item]
    INSTEAD OF UPDATE
    AS 
    BEGIN
      SET NOCOUNT ON;
    
      UPDATE src SET col1 = i.col1 --, ... other columns,
         ModifiedDate = CURRENT_TIMESTAMP
         FROM dbo.Item AS src
         INNER JOIN inserted AS i
         ON src.ItemID = i.ItemID
         INNER JOIN deleted AS d
         ON i.ItemID = d.ItemID 
         WHERE d.BillID IS NULL; 
    
      IF @@ROWCOUNT = 0
      BEGIN
        RAISERROR(...);
      END
    END
    GO
    



    1. ORA-00907:右括弧がありません

    2. 2つの異なるテーブルの列sqlite3に結合します

    3. pgBouncerを使用してPostgreSQLの高可用性を実現する方法

    4. 低RTOでのディザスタリカバリのための複数の遅延レプリケーションスレーブ