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

PostgreSQL9.2.1でトリガー呼び出しのループを回避する方法

    これは、標準トリガーを使用して行うことができます BEFORE UPDATE OF ... ON ...の更新前 。
    CREATE TRIGGERのマニュアル 通知:

    リストされた列の少なくとも1つがUPDATEコマンドのターゲットとして言及されている場合にのみ、トリガーが起動します。

    そしてさらに下へ:

    列固有のトリガー(UPDATE OF column_namesyntaxを使用して定義されたトリガー)は、その列のいずれかがUPDATEコマンドのSETリストにターゲットとしてリストされている場合に起動します。 BEFORE UPDATEトリガーによって行の内容に加えられた変更は考慮されないため、トリガーが起動されていない場合でも列の値が変更される可能性があります。

    大胆な強調鉱山。したがって、トリガー内の更新によって別のトリガーが呼び出されないため、無限ループは発生しません。

    テストケース

    テストテーブルを作成します(簡略化され、無関係な行はありません):

    CREATE TABLE soil_samples (
      pgid SERIAL PRIMARY KEY
    
     ,utm_zone integer
     ,utm_easting integer
     ,utm_northing integer
    
     ,wgs84_longitude double precision
     ,wgs84_latitude double precision
    
     ,yt_albers_geom double precision
    );
    

    最初の要件のダミートリガー:

    utm_zoneの更新が行われたとき 、utm_easting 、またはutm_northing 、次にwgs_84_latitudewgs84_longitude 、およびyt_albers_geom トリガーによって更新されます。

    CREATE OR REPLACE FUNCTION trg_upbef_utm()  RETURNS trigger AS
    $func$
    BEGIN
       NEW.wgs84_latitude  := NEW.wgs84_latitude + 10;
       NEW.wgs84_longitude := NEW.wgs84_longitude + 10;
       NEW.yt_albers_geom  := NEW.yt_albers_geom + 10;
    
       RETURN NEW;
    END
    $func$ LANGUAGE plpgsql;
    
    CREATE TRIGGER upbef_utm
    BEFORE UPDATE OF utm_zone, utm_easting, utm_northing ON soil_samples
    FOR EACH ROW
    WHEN (NEW.utm_zone     IS DISTINCT FROM OLD.utm_zone    OR
          NEW.utm_easting  IS DISTINCT FROM OLD.utm_easting OR
          NEW.utm_northing IS DISTINCT FROM OLD.utm_northing)  -- optional
    EXECUTE PROCEDURE trg_upbef_utm();
    

    WHEN 句はオプションです。実際に値が変更されていないときにトリガーが起動するのを防ぎます。

    2番目の要件のダミートリガー:

    wgs84_latitudeの更新が行われたとき またはwgs84_longitude 、次にすべてのu tm_ yt_albers_geomと同様に、フィールドが更新されます 。

    CREATE OR REPLACE FUNCTION trg_upbef_wgs84()  RETURNS trigger AS
    $func$
    BEGIN
       NEW.utm_zone       := NEW.utm_zone + 100;
       NEW.utm_easting    := NEW.utm_easting + 100;
       NEW.utm_northing   := NEW.utm_northing + 100;
       NEW.yt_albers_geom := NEW.yt_albers_geom + 100;
    
       RETURN NEW;
    END
    $func$ LANGUAGE plpgsql;
    
    CREATE TRIGGER upbef_wgs84
     BEFORE UPDATE OF wgs84_latitude, wgs84_longitude ON soil_samples
     FOR EACH ROW
     WHEN (NEW.wgs84_latitude  IS DISTINCT FROM OLD.wgs84_latitude OR
           NEW.wgs84_longitude IS DISTINCT FROM OLD.wgs84_longitude)  -- optional
     EXECUTE PROCEDURE trg_upbef_wgs84();
    

    これらの線に沿った3番目の要件のトリガー...

    テスト

    INSERT INTO soil_samples VALUES (1, 1,1,1, 2,2, 3) RETURNING *;
    

    upbef_utmをトリガーします :空の更新、何も起こりません:

    UPDATE soil_samples SET utm_zone = 1 RETURNING *;
    

    実際の変更で更新:2番目のトリガーupbef_wgs84 UPDATE OF utm_zoneでは起動しません !

    UPDATE soil_samples SET utm_zone = 0 RETURNING *;
    

    upbef_wgs84をトリガーします :

    UPDATE soil_samples SET wgs84_latitude = 0 RETURNING *;
    

    ->SQLfiddleデモ。




    1. 動的管理ビュー(DMV)を使用したSQLServerTempDBの監視

    2. MS SQL Server方言の例に関するSQL(DDL、DML)のチュートリアル

    3. Oracle10gExpressのホームページが表示されない

    4. SQLServer2008でパラメーター化されたVIEWを作成する