Este tutorial fue probado por nuestros especialistas así aseguramos la veracidad de nuestro contenido.
Solución:
Estaba buscando exactamente lo mismo hace un par de años. ¡Una función de activación para gobernarlos a todos! Pregunté en las listas de Usenet, probé varios enfoques, sin éxito. El consenso al respecto fue esto no se pudo hacer. Una deficiencia de PostgreSQL 8.3 o anterior.
Desde PostgreSQL 8.4 tu puedes sólo:
EXECUTE 'INSERT INTO ' || TG_RELID::regclass::text || ' SELECT ($1).*'
USING NEW;
Con la pg 8.2 tienes un problema:
- no puede acceder dinámicamente a las columnas de
NEW
/OLD
. Debe conocer los nombres de las columnas al momento de escribir la función de activación. NEW
/OLD
no se ven por dentroEXECUTE
.EXECUTE .. USING
no ha nacido todavía.
Sin embargo, hay un truco.
Cada nombre de tabla en el sistema puede servir como tipo compuesto del mismo nombre. Por lo tanto, puede crear una función que tome NEW
/ OLD
como parámetro y ejecutar eso. Puede crear y destruir dinámicamente esa función en cada evento desencadenante:
Función de disparo:
CREATE OR REPLACE FUNCTION trg_cdc()
RETURNS trigger AS
$func$
DECLARE
op text := TG_OP || '_' || TG_WHEN;
tbl text := quote_ident(TG_TABLE_SCHEMA) || '.'
|| quote_ident(TG_TABLE_NAME);
cdc_tbl text := quote_ident(TG_TABLE_SCHEMA) || '.'
|| quote_ident('cdc_' || TG_TABLE_NAME);
BEGIN
EXECUTE 'CREATE FUNCTION f_cdc(n ' || tbl || ', op text)
RETURNS void AS $x$ BEGIN
INSERT INTO ' || cdc_tbl || ' SELECT op, (n).*;
END $x$ LANGUAGE plpgsql';
CASE TG_OP
WHEN 'INSERT', 'UPDATE' THEN
PERFORM f_cdc(NEW, op);
WHEN 'DELETE' THEN
PERFORM f_cdc(OLD, op);
ELSE
RAISE EXCEPTION 'Unknown TG_OP: "%". Should not occur!', TG_OP;
END CASE;
EXECUTE 'DROP FUNCTION f_cdc(' || tbl || ', text)';
IF TG_OP = 'DELETE' THEN
RETURN OLD;
ELSE
RETURN NEW;
END IF;
END
$func$ LANGUAGE plpgsql;
Generar:
CREATE TRIGGER cdc
BEFORE INSERT OR UPDATE OR DELETE ON my_tbl
FOR EACH ROW EXECUTE PROCEDURE trg_cdc();
Los nombres de las tablas deben tratarse como una entrada del usuario. Usar quote_ident()
para defenderse de la inyección de SQL.
Sin embargo, de esta manera crea y suelta una función para cada evento desencadenante. Bastante sobrecarga, yo no iría por eso. Tendrá que aspirar mucho algunas tablas de catálogo.
término medio
PostgreSQL admite la sobrecarga de funciones. Por lo tanto, una función por tabla del mismo nombre básico (pero diferente tipo de parámetro) pueden coexistir. Podría tomar el término medio y reducir drásticamente el ruido creando f_cdc(..)
una vez por tabla al mismo tiempo que crea el disparador. Esa es una pequeña función por tabla. Debe observar los cambios en las definiciones de las tablas, pero las tablas no deberían cambiar con tanta frecuencia. Remover CREATE
y DROP FUNCTION
desde la función de gatillo, llegando a un gatillo pequeño, rápido y elegante.
Podría verme haciendo eso en la página 8.2. Excepto que no puedo verme haciendo cualquier cosa en la página 8.2 más. Llegó al final de su vida útil en diciembre de 2011. Después de todo, tal vez puedas actualizarlo de alguna manera.
Calificaciones y reseñas
Agradecemos que quieras reafirmar nuestra labor exponiendo un comentario y dejando una valoración te damos las gracias.