registros - trigger postgresql example
Cómo evitar las llamadas al Trigger de bucle en PostgreSQL 9.2.1 (1)
Puede hacer esto con activadores estándar BEFORE UPDATE OF ... ON ...
El manual sobre CREATE TRIGGER
informa:
El desencadenador solo se activará si al menos una de las columnas enumeradas se menciona como un objetivo del comando ACTUALIZAR.
Y más abajo:
Se activará un desencadenador específico de columna (uno definido mediante la sintaxis UPDATE OF column_name) cuando cualquiera de sus columnas se enumere como destinos en la lista SET del comando UPDATE. Es posible que el valor de una columna cambie incluso cuando el desencadenador no se active, porque los cambios realizados en los contenidos de la fila ANTES de los activadores de ACTUALIZACIÓN no se tienen en cuenta.
Negrita énfasis mío. Entonces no hay bucles infinitos, porque las actualizaciones dentro del disparador no invocan otro disparador.
Caso de prueba
Crear tabla de prueba (simplificada, sin filas irrelevantes):
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
);
Activador simulado para su primer requisito:
Cuando se realiza una actualización en
utm_zone
,utm_easting
outm_northing
, entonceswgs_84_latitude
,wgs84_longitude
yyt_albers_geom
se actualizan mediante un desencadenador.
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();
La cláusula WHEN
es opcional. Impide que el disparador se dispare cuando ningún valor realmente ha cambiado.
Activador ficticio para su segundo requerimiento:
Cuando se realiza una actualización en
wgs84_latitude
owgs84_longitude
, se actualizan todos los campos utm_
, así comoyt_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();
Desencadenar el tercer requerimiento a lo largo de estas líneas ...
Prueba
INSERT INTO soil_samples VALUES (1, 1,1,1, 2,2, 3) RETURNING *;
Desencadenar upbef_utm
: actualización vacía, no pasa nada:
UPDATE soil_samples SET utm_zone = 1 RETURNING *;
Actualización con cambio real: el segundo activador upbef_wgs84
no se upbef_wgs84
UPDATE OF utm_zone
!
UPDATE soil_samples SET utm_zone = 0 RETURNING *;
Desencadenar upbef_wgs84
:
UPDATE soil_samples SET wgs84_latitude = 0 RETURNING *;
Tengo una mesa:
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)
)
La geometría PostGIS 2.0 en yt_albers_geom
se crea usando un disparador que dispara en INSERTS contra esta tabla. Si el registro que se inserta satisface una de las siguientes condiciones, se genera la geometría:
- Los campos
wgs84_latitude
ywgs84_longitude
no son nulos - Cada uno de
utm_zone
,utm_easting
yutm_northing
no son nulos
Ahora, estoy confundido acerca de cómo hacer actualizaciones que logren lo siguiente:
- Cuando se realiza una actualización en
utm_zone
,utm_easting
outm_northing
, entonceswgs_84_latitude
,wgs84_longitude
yyt_albers_geom
se actualizan mediante un disparador - Cuando se realiza una actualización en
wgs84_latitude
owgs84_longitude
, se actualizan todos los camposutm_
, así comoyt_albers_geom
. - Cuando se realiza una actualización a
yt_albers_geom
, todos los campos de coordenadas se actualizan.
Parece que cualquiera de estos factores desencadenantes causaría un ciclo infinito de activación del disparador, ¿correcto?