sql >> Database >  >> RDS >> PostgreSQL

Hoe u trigger-oproepen in een lus kunt vermijden in PostgreSQL 9.2.1

U kunt dit doen met standaardtriggers BEFORE UPDATE OF ... ON ... .
De handleiding over CREATE TRIGGER informeert:

De trigger wordt alleen geactiveerd als ten minste één van de vermelde kolommen wordt genoemd als doel van het UPDATE-commando.

En verder naar beneden:

Een kolomspecifieke trigger (een trigger die is gedefinieerd met behulp van de UPDATE OF column_namesyntax) wordt geactiveerd wanneer een van zijn kolommen wordt weergegeven als doelen in de SET-lijst van hetUPDATE-commando. Het is mogelijk dat de waarde van een kolom verandert, zelfs als de trigger niet wordt geactiveerd, omdat wijzigingen die door BEFORE UPDATE-triggers in de rij worden aangebracht, niet worden overwogen.

Vetgedrukte nadruk van mij. Dus geen oneindige lussen, omdat de updates binnen de trigger geen andere trigger oproepen.

Testcase

Maak een testtabel (vereenvoudigd, zonder irrelevante rijen):

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

Dummy-trigger voor uw eerste vereiste:

Wanneer een update is uitgevoerd naar utm_zone , utm_easting , of utm_northing , danwgs_84_latitude , wgs84_longitude , en yt_albers_geom worden bijgewerkt door een trigger.

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

De WHEN clausule is optioneel. Voorkomt dat de trigger wordt geactiveerd als er geen waarde is veranderd.

Dummy-trigger voor uw tweede vereiste:

Wanneer een update is uitgevoerd naar wgs84_latitude of wgs84_longitude , dan alle utm_ velden worden bijgewerkt, evenals 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();

Trigger voor derde vereiste in deze zin ...

Test

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

Activeer upbef_utm :lege update, er gebeurt niets:

UPDATE soil_samples SET utm_zone = 1 RETURNING *;

Update met daadwerkelijke wijziging:de tweede trigger upbef_wgs84 zal niet vuren op UPDATE OF utm_zone !

UPDATE soil_samples SET utm_zone = 0 RETURNING *;

Activeer upbef_wgs84 :

UPDATE soil_samples SET wgs84_latitude = 0 RETURNING *;

-> SQLfiddle-demo.




  1. hoe een lijst met 10.000 unieke id's van dual te selecteren in Oracle SQL?

  2. Wat is de limiet van SQL-variabelen die men kan specificeren in een enkele execSQL-query?

  3. MariaDB 10.0 upgraden naar 10.3.9 op Ubuntu 16.04

  4. mysql:waarom geeft het vergelijken van een 'string' met 0 waar?