PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Jak uniknąć zapętlania się wywołań wyzwalaczy w PostgreSQL 9.2.1?

Możesz to zrobić za pomocą wyzwalaczy standardowych BEFORE UPDATE OF ... ON ... .
Instrukcja CREATE TRIGGER informuje:

Wyzwalacz uruchomi się tylko wtedy, gdy co najmniej jedna z wymienionych kolumn zostanie wymieniona jako cel polecenia UPDATE.

I dalej w dół:

Wyzwalacz specyficzny dla kolumny (zdefiniowany przy użyciu składni UPDATE OF nazwa_kolumny) zostanie uruchomiony, gdy którakolwiek z jego kolumn zostanie wymieniona jako cel na liście SET polecenia UPDATE. Możliwe jest, że wartość kolumny zmieni się nawet wtedy, gdy wyzwalacz nie zostanie uruchomiony, ponieważ zmiany w zawartości wiersza dokonane przez wyzwalacze BEFORE UPDATE nie są brane pod uwagę.

Moje odważne podkreślenie. Więc nie ma nieskończonych pętli, ponieważ aktualizacje wewnątrz wyzwalacza nie wywołują innego wyzwalacza.

Przypadek testowy

Utwórz tabelę testową (uproszczona, bez nieistotnych wierszy):

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

Imitacja wyzwalacza dla pierwszego wymagania:

Po zakończeniu aktualizacji utm_zone , utm_easting lub utm_northing , a następnie wgs_84_latitude , wgs84_longitude i yt_albers_geom są aktualizowane przez wyzwalacz.

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 klauzula jest opcjonalna. Zapobiega uruchomieniu wyzwalacza, gdy żadna wartość nie uległa zmianie.

Imitacja wyzwalacza dla drugiego wymagania:

Po zakończeniu aktualizacji wgs84_latitude lub wgs84_longitude , a następnie wszystkie utm_ pola są aktualizowane, podobnie jak 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();

Uruchom trzecie wymaganie w tym zakresie...

Test

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

Uruchom upbef_utm :pusta aktualizacja, nic się nie dzieje:

UPDATE soil_samples SET utm_zone = 1 RETURNING *;

Aktualizacja z rzeczywistą zmianą:drugi wyzwalacz upbef_wgs84 nie uruchomi się po UPDATE OF utm_zone !

UPDATE soil_samples SET utm_zone = 0 RETURNING *;

Uruchom 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. Tabela ze współrzędnymi siatki heksagonalnej, która obejmuje świat

  2. Wyświetlanie obrazu z bazy PostgreSQL, bajta

  3. Przewodnik po Pgpool dla PostgreSQL:część pierwsza

  4. Jak przechowywać tablicę lub wiele wartości w jednej kolumnie?

  5. Wydajność TPC-H od PostgreSQL 8.3