7

私はテーブルを持っています:

CREATE TABLE field_data.soil_samples (
 pgid SERIAL NOT NULL,
 sample_id text,
 project_id text,
 utm_zone integer,
 utm_easting integer,
 utm_northing integer,
 wgs84_longitude double precision,
 wgs84_latitude double precision,
 yt_albers_geom geometry(Point,3578),
 CONSTRAINT soil_samples_pk PRIMARY KEY (pgid)
)

PostGIS 2.0 ジオメトリは、yt_albers_geomこのテーブルに対して INSERTS を実行するトリガーを使用して作成されます。挿入されるレコードが次の条件のいずれかを満たす場合、ジオメトリが生成されます。

  1. wgs84_latitudeとフィールドの両方wgs84_longitudeが null ではない
  2. utm_zoneutm_easting、およびのそれぞれutm_northingが null ではない

今、私は以下を達成する更新を行う方法について混乱しています:

  1. utm_zoneutm_easting、またはに対して更新が行われるとutm_northingwgs_84_latitudewgs84_longitude、およびyt_albers_geomがトリガーによって更新されます。
  2. wgs84_latitudeまたはが更新されると、 だけでなくwgs84_longitudeすべてのutm_フィールドが更新されyt_albers_geomます。
  3. が更新されるとyt_albers_geom、すべての座標フィールドが更新されます。

これらのトリガーのいずれかが、トリガー発火の無限ループを引き起こすようですよね?

4

1 に答える 1

8

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

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

そしてさらに下に:

列固有のトリガー(UPDATE OF column_name構文を使用して定義されたトリガー)は、その列のいずれかが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_eastingutm_northingwgs_84_latitudewgs84_longitudeyt_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と、すべてのutm_フィールドと。が更新され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デモ。

于 2012-12-02T02:56:52.270 に答える