0

テーブルへの UPDATE を追跡するトリガーの場合、削除と挿入の 2 つの一時テーブルが参照される場合があります。主キーで INNER JOIN を使用せずに 2 つを相互参照する方法はありますか?

私は外部キーなしで参照整合性を維持しようとしているので (聞かないでください)、トリガーを使用しています。テーブル A の主キーへの UPDATE がルックアップ テーブル B の「外部キー」に反映され、テーブル A の複数のレコードに UPDATE が影響する場合に発生するようにしたい。

私が見たすべての UPDATE トリガーの例は、挿入されたテーブルと削除されたテーブルを結合して変更を追跡することにかかっています。そして、更新されたテーブルの ID フィールド (主キー) を使用して結合を設定します。しかし、その ID フィールド (GUID) がレコード (またはレコードのセット) で変更されたフィールドである場合、それらの変更を追跡して、対応するルックアップ テーブルでそれらの変更を適用できるようにする良い方法はありますか?

4

2 に答える 2

0

私はちょうどこの問題(というか、似たような問題)を抱えていたので、復活しました...

私の最終的なアプローチは、トリガーを壊すという理由だけで PK フィールドへの更新を単純に禁止することでした。ありがたいことに、主キー列の更新をサポートするビジネス ケースがなかったので (とにかく、これらはサロゲート ID でした)、それでうまくいくことができました。

SQL Server は、UPDATEトリガー内で使用するために、このエッジ ケースをチェックする関数を提供します。

CREATE TRIGGER your_trigger
ON your_table
INSTEAD OF UPDATE
AS BEGIN

    IF UPDATE(pk1) BEGIN
        ROLLBACK

        DECLARE @proc SYSNAME, @table SYSNAME

        SELECT TOP 1
             @proc = OBJECT_NAME(@@PROCID)
            ,@table = OBJECT_NAME(parent_id)
        FROM sys.triggers 
        WHERE object_id = @@PROCID

        RAISERROR ('Trigger %s prevents UPDATE of table %s due to locked primary key', 16, -1, @proc, @table) WITH NOWAIT
    END
    ELSE UPDATE t SET
         col1 = i.col1
        ,col2 = i.col2
        ,col3 = i.col3
    FROM your_table t
    INNER JOIN inserted i ON t.pk1 = i.pk1

END
GO

(上記はテストされておらず、おそらくXACT_STATEorに関するあらゆる種類の問題が含まれていることに注意してくださいTRIGGER_NESTLEVEL-- 原理を示すためだけに存在します)

ただし、少し面倒なので、開発中にテーブルへの変更を処理するために、コード生成を検討します (おそらく、CREATE/ALTER テーブルの DDL トリガーによって行われることもあります)。

複合主キーがある場合は、関数を使用するIF UPDATE(pk1) OR UPDATE(pk2)...か、COLUMNS_UPDATED関数でビット単位の作業を行うことができます。これにより、列の序数に基づいてビットマスクが得られます (ただし、ここでは説明しません。MSDN/BOL を参照してください)。

他の (より単純な) オプションは toですが、 (そしておそらく)DENY UPDATE ON your_table(pk) TO publicのメンバーはこれを尊重しないことに注意してください。sysadminsdbo

于 2014-03-31T18:14:47.567 に答える