PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Cara Menghindari Looping Trigger Calls Di PostgreSQL 9.2.1

Anda dapat melakukannya dengan pemicu standar BEFORE UPDATE OF ... ON ... .
Manual tentang CREATE TRIGGER menginformasikan:

Pemicu hanya akan diaktifkan jika setidaknya salah satu kolom yang terdaftar disebutkan sebagai target dari perintah UPDATE.

Dan lebih jauh ke bawah:

Pemicu khusus kolom (yang ditentukan menggunakan sintaks UPDATE OF column_name_name) akan diaktifkan ketika salah satu kolomnya terdaftar sebagai target dalam daftar SET perintah UPDATE. Nilai kolom dapat berubah meskipun pemicu tidak diaktifkan, karena perubahan yang dibuat pada konten baris oleh pemicu SEBELUM UPDATE tidak dipertimbangkan.

Penekanan saya yang berani. Jadi tidak ada infinite loop, karena pembaruan di dalam trigger tidak memanggil trigger lain.

Kasus uji

Buat tabel pengujian (disederhanakan, tanpa baris yang tidak relevan):

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
);

Pemicu tiruan untuk persyaratan pertama Anda:

Saat pembaruan dilakukan pada utm_zone , utm_easting , atau utm_northing , laluwgs_84_latitude , wgs84_longitude , dan yt_albers_geom diperbarui oleh pemicu.

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 klausa adalah opsional. Mencegah pemicu diaktifkan saat tidak ada nilai yang benar-benar berubah.

Pemicu tiruan untuk persyaratan kedua Anda:

Saat pembaruan dilakukan pada wgs84_latitude atau wgs84_longitude , lalu semua utm_ bidang diperbarui, serta 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();

Pemicu untuk persyaratan ketiga di sepanjang baris ini ...

Uji

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

Memicu upbef_utm :pembaruan kosong, tidak ada yang terjadi:

UPDATE soil_samples SET utm_zone = 1 RETURNING *;

Perbarui dengan perubahan aktual:Pemicu kedua upbef_wgs84 tidak akan aktif pada UPDATE OF utm_zone !

UPDATE soil_samples SET utm_zone = 0 RETURNING *;

Memicu upbef_wgs84 :

UPDATE soil_samples SET wgs84_latitude = 0 RETURNING *;

-> Demo SQLfiddle.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana saya bisa menghapus semua tabel dalam database PostgreSQL?

  2. CTE dan Paradoks Ulang Tahun

  3. Mengonversi Kumpulan Hasil dari SQL Array ke Array of Strings

  4. PostgreSQL :berikan string hingga saat ini DD/MM/YYYY

  5. Gunakan alamat email sebagai kunci utama?