PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Как да избегнем повтарящи се тригерни повиквания в PostgreSQL 9.2.1

Можете да направите това сстандартни тригери BEFORE UPDATE OF ... ON ... .
Ръководството за CREATE TRIGGER информира:

Тригерът ще се задейства само ако поне една от изброените колони е спомената като цел на командата UPDATE.

И по-надолу:

Специфичен за колона тригер (дефиниран с помощта на UPDATE OF column_namesyntax) ще се задейства, когато някоя от колоните му е изброена като цели в списъка SET на командата 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_latitude , wgs84_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 клаузата е незадължителна. Предотвратява задействането на спусъка, когато стойността не се е променила.

Фактично задействане за второто ви изискване:

Когато се направи актуализация на 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();

Задействане за третото изискване по тези редове...

Тест

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

Задействайте upbef_utm :празна актуализация, нищо не се случва:

UPDATE soil_samples SET utm_zone = 1 RETURNING *;

Актуализация с действителна промяна:Вторият тригер 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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Rails:Няма пул за връзки за ActiveRecord::Base

  2. Postgres аналог на CROSS APPLY в SQL Server

  3. Обхват на релсите - къде в точни съвпадения

  4. PostgreSQL:Кой тип данни трябва да се използва за валута?

  5. Изберете произволен ред за всяка група