No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Curso de PostgreSQL

Curso de PostgreSQL

Oswaldo Rodríguez González

Oswaldo Rodríguez González

Triggers

23/32
Recursos

Aportes 121

Preguntas 10

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

Quedé en la nebulosa con esta lección.

23. Triggers
Para la creación de triggers se debe hacer los siguiente
Crear la función que activará el evento. Para ello se debe tomar los siguientes aspectos:

  1. En la declaración de la función, en la sección del retorno se debe indicar que es tipo triggers es decir RETURNS TRIGGER.
    Luego indicar en que lenguaje está escrito es decir LANGUAE ‘plpgsql’

  2. La función tipo triggers debe retornar los valores OLD acepta lo viejo o NEW acepta lo nuevo. Sí se retorna VOID en nuestra función de tipo triggers no aceptamos cambios es decir RETURN NEW;

  3. Tanto NEW como OLD son un objeto de tipo record y contiene dentro de si el registro, es decir se puede acceder a los campos NEW.campo_nombre del registro

DROP FUNCTION IF EXISTS  count_on_insert_pasajero() CASCADE;

CREATE OR REPLACE FUNCTION count_on_insert_pasajero()
	RETURNS TRIGGER
	LANGUAGE 'plpgsql'
AS $BODY$
	DECLARE 
		contador integer:=0;
		rec record;
	BEGIN
		
		FOR rec IN SELECT * FROM pasajero LOOP 
			contador := contador + 1;
		END LOOP;
		RAISE NOTICE 'cantidad de registros:	%', contador;
		
		--insert record on conteo_pasajero
		INSERT INTO public.conteo_pasajero (total_pasajero,hora_conteo)
		VALUES (contador,now());
		
		RETURN NEW;
		
	END;	
$BODY$

Lo siguiente será crear la regla que estará a la escucha del evento para disparar el triggers, para ello se deberá tomar los siguientes aspectos.

  1. CREATE TRIGGER name_trigger name_event ON name_table FOR EACH ROW EXECUTE PROCEDURE name_procedure;

  2. En la primera sección cuando declaramos el trigger debemos indicar en que momento en que se debe disparar el trigger:
    CREATE TRIGGER name_trigger name_event ON name_table en el name_event allí puede ir alguno de estos tres parámetros para llamar la ejecución del trigger, estos son:

  • BEFORE = antes,

  • AFTER=luego,

  • INSTEAD OF = hacer esto, en vez de lo que iba a hacer el motor de bases de datos.

  1. FOR EACH ROW EXECUTE PROCEDURE name_procedure indica que es para registro o fila de nuestra tabla
-- CREACIÓN DE LA REGLA PARA EJECUTAR EL TRIGGER
CREATE TRIGGER trigger_on_insert_to_pasajero
AFTER INSERT ON pasajero 
FOR EACH ROW EXECUTE PROCEDURE count_on_insert_pasajero(); 

Creo que los procedimientos a explicar en esta clase fueron muy dispersos. Comparto un pequeño tutorial que resume en pocos pasos como crear un trigger.
Triggers

![](

¿Que son los triggers?
En este contexto, los triggers, al igual que las tablas, son objetos en los cuales podemos programar unas instrucciones con el fin de que se disparen (he ahí su nombre) cuando haya un evento (cambio) en la tabla relacionada. No puede haber trigger sin ser relacionada a una tabla.
Los cambios que puede tener una tabla pueden ser (update, insert, delete).
¿Para qué necesitamos los triggers?
Un ejemplo claro sería, que como administrador de la base de datos, necesitamos tener un control y saber que usuarios han estado interactuando con la base de datos disparando dichos eventos.
¿Qué acciones puede realizar un trigger?
Un trigger puede dispararse ya sea antes, después o en lugar de, de un evento. Por ejemplo: Un usuario al ingresar datos a una tabla por medio del comando Insert, el trigger puede ejecutarse justo antes almacenando en otra tabla información relacionada sobre. ¿quien lo hizo?, la hora, cantidad de datos agregados, etc. Y se hará de forma automática
También se puede por ejemplo antes de ejecutar el comando update, hacer una copia de respaldo.
Usualmente los triggers se relacionan con el mantenimiento y administración de las bases de datos.

Esta clase creo que estuvo muy compleja

Hay que tener cuidado con los Triggers y no usarlos en la logica del negocio porque pueden volverse un dolor de cabeza, yo solo los utilizo para realizar el llenado de alguna tabla de auditoria, ya que las variables OLD y NEW te permiten saber que campos sufrieron modificaciones, y solo registrar los campos que se modifican.

Solo agregué al Trigger en la línea del

AFTER INSERT

👇

AFTER INSERT OR DELETE

y funciona perfectamente.

DROP FUNCTION IF EXISTS count_on_insert_pasajero() CASCADE; en ocasiones para borrar una función de tipo triggers nos arrojará error porque de esta función dependen otros objetos y debemos utilizar CASCADE

Falta un curso con mas detalles sobre triggers y sobre el manejo del código

Esta clase se hizo complicada innecesariamente confundiendo a los que recien empezamos con BD. Creo que el profesor debio revisar antes sus consultas para no mostrar tantos errores que no hacian mas que confundir.

Los triggers son de gran ayuda, ya que permiten poblar bitácoras (por ejemplo) al momento de realizar inserts o updates dentro de tablas contenidas dentro de nuestro sistema. Su estructura es:

  • Creación de función con tipo de RETURN TRIGGER.
  • Creación de trigger asociado a una acción y momento concreto sobre una tabla [AFTER, BEFORE, INSTEAD] [UPDATE,INSERT,DELETE,TRUNCATE]

Creo que esta clase fue más revuelta de lo necesaria. De manera muy sencilla:
Imaginemos que tenemos una tienda y vendemos celulares.
Por cada compra que tenemos, usamos un trigger para indicar que se compró un celular, al momento en que ingresa dinero en nuestro negocio por la venta, se dispara el trigger para indicar que un celular se fue de nuestro stock. En vez de hacerlo de forma manual, es de forma automática.

No era necesario eliminar el trigger y volver a crear todo ya que el tipo de retorno definido era el mismo.

CREATE TRIGGER snapshot_passengers_trigger
AFTER INSERT OR DELETE 
ON passengers
FOR EACH ROW
EXECUTE PROCEDURE snapshot_passengers_procedure();

También conocidos como disparadores. Permiten ejecutar funciones dependiendo de acciones que se ejecuten dentro de una DB.
Insert.
Update.
Delete.
Primero validamos la función, y que podamos guardar datos en una nueva tabla que hemos creado, para este caso se llamará ‘passenger_counter’. Seleccionamos en el menú desplegable las funciones, la función que vamos a editar, en este caso es testPL, y añadimos la función para añadir la cantidad de pasajeros.

CREATE OR REPLACE FUNCTION public."testPL"(
	)
    RETURNS integer
    LANGUAGE 'plpgsql'

    COST 100
    VOLATILE 
    
AS $BODY$DECLARE
rec record;
counter integer := 0;
BEGIN
	FOR rec IN SELECT * FROM passenger LOOP
		RAISE NOTICE 'Un pasajero se llama %', rec.name;
		counter := counter + 1;
	END LOOP;
	INSERT INTO passenger_counter (total, time)
	VALUES (counter, now());
	RETURN counter;
END$BODY$;

ALTER FUNCTION public."testPL"()
    OWNER TO postgres;

Ya que funciona, ahora la función no puede devolver un tipo de dato integer, sino un tipo de dato trigger. Elíminamos el RETURN porque al ser un trigger no returna ningún tipo de dato.

CREATE OR REPLACE FUNCTION public."testPL"(
	)
    RETURNS TRIGGER
    LANGUAGE 'plpgsql'
AS $BODY$DECLARE
rec record;
counter integer := 0;
BEGIN
	FOR rec IN SELECT * FROM passenger LOOP
		counter := counter + 1;
	END LOOP;
	INSERT INTO passenger_counter (total, time)
	VALUES (counter, now());
END$BODY$;

Borramos la función anterior con DROP FUNCTION y volvemos a crear la nueva función con el retorno de dato de tipo trigger.
Para crear un trigger tenemos 3 tipos de disparadores
BEFORE: Antes de que se hagan los cambios.
AFTER: Después que se hagan los cambios.
INSTEAD OF: En vez de hacer los cambios.
Y ahora creamos el trigger de la siguiente manera:

CREATE TRIGGER my_trigger // Creamos el trigger y le ponemos el nombre my_trigger
AFTER INSERT // Después de insertar
ON passenger // En la tabla pasajero
FOR EACH ROW // Para cada fila
EXECUTE PROCEDURE "testPL"(); // Ejecutar el procedimiento/función "testPL"()

Ahora, al momento de crear una fila nos arrojará un error, ¿por qué? porque el trigger tiene que retornarnos que se ha creado un dato.
Primero hay que eliminar los triggers y las funciones, como la función es un trigger, se encuentra en el menú desplegable “trigger functions”.
Vuelve y se crea la función, y el trigger con el siguiente código.

DROP FUNCTION public."testPL"();

CREATE FUNCTION public."testPL"()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF
AS $BODY$DECLARE
rec record;
counter integer := 0;
BEGIN
	FOR rec IN SELECT * FROM passenger LOOP
		counter := counter + 1;
	END LOOP;
	INSERT INTO passenger_counter (total, time)
	VALUES (counter, now());
	RETURN NEW; // NEW es para retornar los datos nuevos que se están ingresando, OLD retorna los valores antiguos. Como estamos insertando valores, se necesita retornar los datos que estamos ingresando
END$BODY$;

ALTER FUNCTION public."testPL"()
    OWNER TO postgres;

CREATE TRIGGER my_trigger
    AFTER INSERT
    ON public.passenger
    FOR EACH ROW
    EXECUTE PROCEDURE public."testPL"();

RETO CREAR UN TRIGGER PARA CUANDO SE BORRE UN DATO DE LA TABLA.

CREATE TRIGGER delete_trigger
    AFTER DELETE
    ON public.passenger
    FOR EACH ROW
    EXECUTE PROCEDURE public."testPL"();

No necesitamos crear una función de más, simplemente usamos la función anterior para que cuente los registros, y que se ejecute después que se borre un registro.

El profe: VIste lo fácil que es crear un trigger
Yo: Claro mister, solo dejeme ver la clase unas 5 veces más. Solo es para verificar :'v

Los tirggers son un gran mecanismo para colocar codigo de los aplicativos en la capa de base de datos y validar logica. Hay que tener mucho cuidado en tablas de alta transaccionalidad ya que pueden generar un cuello de botella en el rendimeinto.

Mi aporte

CREATE TRIGGER mitrigger2 --Crea el trigger con nombre
AFTER DELETE --Hazlo despues de AFTER o antes BEFORE
ON pasajero -- que que tabla
FOR EACH ROW -- Cada cuando por cada fila
EXECUTE PROCEDURE importantepl(); --y ejecuta la funcion

funcionó excelente clase ,

Esta clase estuvo super compleja…se que esta de parte nuestra buscar mas informacion…creo que la estructura de este capitulo no fue el mejor para explicar esta leccion.

Resulta muy difícil llevar la secuencia al profesor.

Hola les comparto la solucion al reto
una ligera modificacion en el PL
RETURN OLD en lugar de NEW

-- FUNCION PARA DISMINUIR EN CASO DE ELIMINACION
CREATE OR REPLACE FUNCTION public.borrarPasajero()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
	rec record:= NULL;
	contador integer:=0;
BEGIN
	FOR rec IN SELECT * FROM pasajero LOOP
		contador:= contador+1;
	END LOOP;
	INSERT INTO conteo_pasajeros (total, fecha)
	VALUES (contador, now());
	-- para que no de error de no retornar nada
	RETURN OLD;
END
$BODY$;

ALTER FUNCTION public.borrarPasajero()
    OWNER TO postgres;

Y luego el triger asociado a la tabla pasajeros poniendo AFTER DELETE

-- TRIGGER AFTER DELETE
CREATE TRIGGER AD_conteo_pasajeros
AFTER DELETE 
ON pasajero
FOR EACH ROW
EXECUTE PROCEDURE "borrarpasajero"();

Hola a @todos les comparto el trigger creado para el caso del borrado de registro en la tabla pasajero , en este caso se utiliza la misma función pl ya que esta contabiliza el total
de registros de la tabla pasajeros

CREATE TRIGGER delete_trigger
AFTER DELETE
ON pasajero
FOR EACH ROW
EXECUTE PROCEDURE impl();

Información resumida de esta clase
#EstudiantesDePlatzi

  • Con lo TRIGGERS podemos ejecutar funciones dependiendo de acciones que se ejecuten en una tabla

  • Recordemos crear una llave primaría cuando creemos una tabla, esto es una buena práctica

  • Las funciones sobre las que podemos adjuntar un TRIGGERS son: INSERT, UPDATE Y DELETE

  • Los TRIGGERS tienen dos variables globales muy importantes; OLD y NEW, estos tienen sentido cuando hacemos un UPDATE

Hay algo muy importante que no quedo muy claro diria yo que es el uso de OLD y NEW. Lo cual es super importante.

Digamos que creamos una tabla para llevar registro de los cambios de dirección de un pasajero sta tabla será:

CREATE TABLE historial_direccion_pasajeros(
id serial NOT NULL,
direccion_anterior VARCHAR(255),
direccion_nueva VARCHAR(255),
fecha_actualizacion timestamp,
usuario VARCHAR(36);
CONSTRAINT historial_direccion_pasajeros_pk PRIMARY KEY(id)
);

En la tabla vamos a llevar registro de la direccion de los usuarios anterior y la que se va a actualizar, además de la fecha de modificación y quien lo hizo.

Para eso creamos la funcion:

CREATE OR REPLACE FUNCTION update_direccion()
RETURNS TRIGGER
AS $$
BEGIN
	INSERT INTO historial_direccion_pasajeros(direccion_anterior, direccion_nueva, fecha_actualizacion, usuario)
	VALUES (OLD.direccion, NEW.direccion, NOW(), CURRENT_USER);
	RETURN NEW;
END;
$$ LANGUAGE plpgsql;

En esa función usamos OLD y NEW, OLD viene siendo la información que se tiene antes de actualizar y NEW la que es después de actualizar. También se hace uso de la palabra reservada o comando CURRENT_USER para tomar el usuario que realizó la acción.

En el trigger sería:

CREATE TRIGGER historial_direccion
BEFORE UPDATE
ON pasajeros
FOR EACH ROW
EXECUTE PROCEDURE update_direccion();

De esa manera cada vez que se actualice la información quedará el registro.

**PD: Escribiendo este post me di cuenta que debí incluir el id del pasajero para saber a quien se le actualizó la dirección. También me puse a pensar si hay alguna forma de que el trigger se dispare si es que se actualiza la columna dirección ya que actualmente cada vez que se modifique cualquier campo de un pasajero se dis para. Supongo que sería algo como hacer una logica condicional en la funcion comparando el OLD.direccion y el NEW.direccion y si son iguales que no inserte nada. **

Primero se debe eliminar el trigger existente.

CREATE TRIGGER mitrigger
    AFTER INSERT OR DELETE
    ON public.pasajero
    FOR EACH ROW
    EXECUTE FUNCTION public."listNamesPL_2"();

Cree el trigger, diciendole que despues de hacer Delete a la tabla pasajeros, por cada fila afectada me ejecute la funcion firstpl()

CREATE TRIGGER DeleteConteoPasajeros
    AFTER DELETE
    ON public.pasajeros
    FOR EACH ROW
    EXECUTE FUNCTION public.firstpl();

Funcion firstlp()

CREATE FUNCTION public.firstpl()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
rec record:= null;
contador integer := 0;
BEGIN
	FOR rec IN SELECT * FROM pasajeros LOOP
	contador := contador + 1;
	END LOOP;
	INSERT INTO conteo_pasajero(total, tiempo)
	VALUES(contador, now());
	RETURN NEW;
END
$BODY$;

Luego procedi a borrar dos registros de la tabla pasjeros

DELETE FROM public.pasajeros
	WHERE id in(11,12);

Selecciono nuevamente los registros de conteo_pasajeros

Como pueden ver al eliminar dos registros de un solo delete, en la tabla conteo pasajeros me inserto dos veces el conteo. No me esperaba esto, ya que esperaba que en la tabla me quedara 105,104 y 103. Como podría hacer para que me quede así?

Cambie el mismo trigger que teníamos agregando solo DELETE

CREATE TRIGGER mitrigger
AFTER INSERT OR DELETE
ON pasajero
FOR EACH ROW
EXECUTE PROCEDURE public."importantePL3"();```

Tarea resuelta:

Les comparto mi reto

-- Trigger para accionar una tabla que muestra un registro cuando se eliminen los rows.

CREATE TRIGGER eliminandotrigger
AFTER DELETE
ON pasajeros
FOR EACH ROW
EXECUTE PROCEDURE importantepl();

DELETE FROM public.pasajeros
	WHERE id = 100;
		
select *
from conteo_pasajeros;

aqui estoy usando triggers para hacer una especie de papelera y no borrar la información de forma definitiva.
.
la idea es borrar un pasajero pero que la info quede guardada en otra tabla por si hay que restablecerlo
pero como las foraneas no permiten hacer el DELETE, se debe borrar primero las referencias de ese pasajero y almacenarlas en otra tabla.
-> lo primero es crear dos tablas una cada una para almacenar la información que vamos a borarr de la otra
-> luego creamos la función para el trigger delete de la tabla pasajeros y usamos before para copiar la información de la tabla, y en esta función borramos las referencias de la tabla viajes.
-> y a la tabla viajes le hacemos una funcion trigger para que guarde los datos antes de ser borrados
==> asi solo hacer un delete en la tabla pasajeros se transfiere y borra la informacion con un solo comando

--------------------papelera-pasajeros-------------------
drop trigger if exists trigger_pasajero_borrado on public.pasajeros;
drop function cascade public.pasajero_borrado;

create or replace function  public.pasajero_borrado () returns trigger
as $$
declare
    
begin
    delete from public.viajes where pasajeros_id = old.id;
    insert into public.pasajeros_borrados
        (nombre, direccion, fecha_nacimiento, pasajeros_id, fecha_eliminacion)
    values (old.id, old.direccion, old.fecha_nacimiento, old.id, now());
    return old;
end
$$
language plpgsql;

create trigger trigger_borrar_pasajero 
before delete on public.pasajeros for each row
execute procedure pasajero_borrado();

--------------------papelera-viajes----------------------
drop trigger if exists trigger_viaje_borrado on public.viajes;
drop function if exists public.viaje_borrado;

create or replace function public.viaje_borrado () returns trigger
as $$
declare

begin
    INSERT INTO public.viajes_borrados
        (viajes_id, pasajeros_id, trayectos_id, inicio, fin)
        VALUES (old.id, old.pasajeros_id, old.trayectos_id, old.inicio, old.fin);
        return old;
end
$$
language plpgsql

create trigger trigger_viaje_borrado 
before delete on public.viajes for each row
execute procedure viaje_borrado();

------------------pruebas-------------------------------
delete from public.pasajeros where id = 4;
delete from public.pasajeros where id = 7;

select * from public.pasajeros;
select * from public.pasajeros_borrados;
select * from public.viajes_borrados;

Esto si lo practicaré con más calma luego, seguir el ritmo es abrumador ya que soy basico en SQL

Como seguirle el paso si el mismo profe se equivoca? imposible llevarle la secuencia al video

Los triggers cuentan con dos variables globales que son importantes, OLD y NEW. OLD se refiere a lo que estaba antes del cambio y NEW es el cambio, se debe especificar que es NEW si se quiere que se haga el cambio (Esto tiene sentido si se esta haciendo el update)

siempre para una auditoria en los tiggers es fundamental saber quien usuario modifico, inserto o elimino la tabla eso se hace dentro la de funcion donde insertamos los values con el nombre
current_user

No era necesario borrar el trigger, me dejo modificarlo

Usando CREATE OR REPLACE sobre el Trigger se puede hacer el reto sin tener que hacer DROP antes de modificar:

CREATE OR REPLACE TRIGGER mitrigger
    AFTER INSERT OR DELETE
    ON public.pasajero
    FOR EACH ROW
    EXECUTE FUNCTION public.conteopa_pgadmin();

RETO:

-- Trigger: mitrigger

-- DROP TRIGGER IF EXISTS mitrigger ON public.pasajeros;

CREATE TRIGGER mitrigger
    AFTER INSERT OR DELETE
    ON public.pasajeros
    FOR EACH ROW
    EXECUTE FUNCTION public."importantePL"();

Un Trigger de base de datos es un programa almacenado que se dispara o ejecuta automáticamente cuando se producen algunos eventos.
Un trigger puede ejecutarse en respuesta a cualquiera de los siguientes eventos:

  1. Una sentencia de manipulación de la base de datos (DML) como DELETE, INSERT o UPDATE.
  2. Una sentencia de definición de la base de datos (DDL) como CREATE, ALTER o DROP.
  3. Una operación de base de datos como SERVERERROR, LOGON, LOGOFF, STARTUP o SHUTDOWN.
    Nota: Un disparador puede definirse en la tabla, vista, esquema o base de datos a la que se asocia el evento.

Sintaxis para crear un Trigger

CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE | AFTER | INSTEAD OF }
{INSERT [OR] | UPDATE [OR] | DELETE}
[OF col_name]
ON table_name
[REFERENCING OLD AS o NEW AS n]
[FOR EACH ROW]
WHEN (condition)
BEGIN
— sql statements
END;

Información tomada de W3schools

oooe sto esta genial. porque ayuda mucho para hacer consultas de forma rapidísima

Este es el código que hice para realizar el conteo sirve tanto para el trigger de inserción como de eliminación.

CREATE OR REPLACE FUNCTION registro_pasajero()
RETURNS trigger
AS $$
	DECLARE
	contador integer;
	BEGIN
		contador := (SELECT COUNT(id)::integer FROM pasajeros);
		INSERT INTO conteo_pasajeros(conteo, fecha)
		VALUES (contador, NOW());
		RETURN NEW;
	END;
$$ LANGUAGE plpgsql;

El crear el trigger no es tan dificil, lo dificil es crear la funcion para conectar con el trigger.

Aunque como ya se tenia la base de la anterior simplemente cree otra tabla para almacer los datos y ajuste las variables.

CREATE OR REPLACE FUNCTION public.borradin()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
rec record;
contador integer := 0;

BEGIN
	FOR rec IN SELECT * FROM pasajero LOOP
		contador := contador + 1;
		END LOOP;
		INSERT INTO menos_pasajeros (total, tiempo)
		VALUES (contador, now());
		RETURN NEW;
END
$BODY$;

Y ya este es el trigger

	CREATE TRIGGER menos
    AFTER DELETE
    ON public.pasajero
    FOR EACH ROW
    EXECUTE FUNCTION public.borradin();

– Puedo asociar un segundo trigger a la misma función. Por ejemplo para dejar registrado los deletes de mi tabla de pasajeros de esta forma

CREATE TRIGGER mitrigger2
	AFTER DELETE
	ON public."PASAJERO"
	FOR EACH ROW
	EXECUTE PROCEDURE public.impl();
...

CREATE FUNCTION public.importanteDelete()
RETURNS trigger
LANGUAGE 'plpgsql’
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
rec record;
BEGIN
FOR rec IN SELECT COUNT(*) as cont FROM pasajero LOOP
INSERT INTO cont_pasajero (total, tiempo)
VALUES (rec.cont, now());
RETURN NEW;
END LOOP;
END
$BODY$;

CREATE TRIGGER mitriggerdelete
AFTER DELETE
ON public.pasajero
FOR EACH ROW
EXECUTE FUNCTION public.importanteDelete();

Algo importamte a resaltar un TRIGGER no se deja modificar cuando se ha cambiado el retorno, por lo tanto se debe:

  1. Borrar TRIGGER
  2. Borrar función
  3. Crear función
  4. Borrar TRIGGER

CREATE OR REPLACE FUNCTION public.importantepl()
RETURNS trigger
LANGUAGE 'plpgsql’
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
rec record;
contador integer := 0;
BEGIN
FOR rec IN SELECT * FROM pasajero LOOP
contador := contador +1;
END LOOP;
INSERT INTO cont_pasajero(total, tiempo)
VALUES (contador, now());
RETURN NEW;
END
$BODY$;

CREATE TRIGGER mitrigger
AFTER INSERT OR DELETE
ON public.pasajero
FOR EACH ROW
EXECUTE FUNCTION public.importantepl();

DELETE FROM public.pasajero WHERE id=103;

pues el trigger me queda claro pero lo que sigo sin entender es el PL. Me voy a saltar esta clase y regresare dentro de unos dias aunque aun asi no creo entender su estructura y como funciona

CREATE OR REPLACE FUNCTION impl()
RETURNS TRIGGER
AS
$$
	DECLARE
		rec record;
		contador integer:=0;
	BEGIN
		FOR rec IN SELECT * FROM public.pasajero LOOP
			contador:=contador+1;
		END LOOP;
		INSERT INTO public.cont_pasajero (total, tiempo)
		VALUES(contador,now());
	END

$$
LANGUAGE PLPGSQL;

SELECT impl();
SELECT * FROM public.cont_pasajero;

ALTER FUNCTION public."importantepl"()
RENAME TO impl;

CREATE TABLE public.cont_pasajero (
	id serial,
	total integer,
	tiempo time with time zone
);
ALTER TABLE public.cont_pasajero ADD
PRIMARY KEY (id);
ALTER TABLE public.cont_pasajero
OWNER TO postgres;

CREATE TRIGGER mitrigger
AFTER INSERT OR DELETE
ON public.pasajero
FOR EACH ROW
EXECUTE PROCEDURE public.impl();

DELETE
FROM public.pasajero
WHERE id=104;
CREATE TRIGGER triggerBorrar
AFTER DELETE
ON public."Pasajero"
FOR EACH ROW
EXECUTE PROCEDURE public."importante_PL"();

Script

-- Trigger Functions->impl()->Create->Trigger function...
-- Esto se convirtio de FUNCTION a TRIGGER, según el orden que despliega pgAdmin

-- FUNCTION: public.impl()

DROP FUNCTION IF EXISTS public.impl();

CREATE OR REPLACE FUNCTION public.impl()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
rec record;
contador integer:=0;
BEGIN
FOR rec IN SELECT * from pasajero LOOP
	contador:= contador +1;
END LOOP;
INSERT INTO cont_pasajero (total, tiempo)
VALUES (contador, now());
-- OLD: 
-- En este caso OLD no sería nada
-- NEW
-- En este caso NEW tendría toda la información

-- Yo: Parece que trabajan como si fueran los constructores de un objeto (OOP): 
-- OLD.id, OLD.fecha, OLD.nombre así como NEW.id, etc.

-- Profesor: Lo que aceptamos es lo que estamos insertando
 RETURN NEW;
 
-- Se hicieron estos cambios (RETURN NEW) debido al error:
-- ERROR:  control reached end of trigger procedure without RETURN
-- CONTEXT:  PL/pgSQL function impl()
-- SQL state: 2F005

-- De insertar una instancia en la tabla pasajero(s)
END
$BODY$;

-- Integración de un TRIGGER a una TABLA usando un impl ("PL")
CREATE TRIGGER mitrigger
-- Qué se va a ejecutar después de un insert
AFTER INSERT OR DELETE 
-- En la tabla pasajero
ON pasajero
-- Ejecutarlo por fila
FOR EACH ROW
EXECUTE PROCEDURE impl();

INSERT INTO pasajero (nombre, direccion_residencia, fecha_nacimiento) 
VALUES ('Nombre Trigger', 'Dir acá', '2000-01-01');

La clase me resultó aclaratoria. Pero el tema de triggers lo había visto antes en el curso de:
PostgreSQL Aplicado a Ciencia de Datos:
https://platzi.com/clases/postgresql-datos/
Específicamente en esta clase:
https://platzi.com/clases/1780-postgresql-datos/25514-plpgsql-conteo-registro-y-triggers/

-- Trigger: borrar

-- DROP TRIGGER borrar ON public.pasajero;

CREATE TRIGGER borrar
    AFTER DELETE
    ON public.pasajero
    FOR EACH ROW
    EXECUTE FUNCTION public.impl();

Tenía miedo de hacer el reto pero me salió a la primera. Era más fácil de lo que parecía 😄

Les presento a mytrigger2

CREATE TRIGGER mytrigger2
AFTER DELETE
ON pasajero
FOR EACH ROW
EXECUTE PROCEDURE mipl();

Hola a todos,
En mi caso cree un nueva función y después cree otro trigger para que me inserte el conteo de filas al momento de realizar una eliminación.

Todo comentario es bienvenido 😄

Para el trigger al borrar pasajeros: DEL_TRIGGER

Resultado después de borrar 4 registros

Por qué fácil si complicado es mejor…

Triggers

CREATE trigger miborratrigger
AFTER DELETE
on public.pasajero
FOR EACH ROW
EXECUTE PROCEDURE import();

Los triggers son como los eventos en Javascript… ocurre una acción y respondes con una función.

OLD & NEW


OLD Hace referencia a los datos que habían antes en tu ‘row’.
NEW Hace referencia a los nuevos datos que estás tratando de ingresar.

Quiero que veas algo:

Si envías estas variables a los LOGS podrás ver que:

  • Si la variable tiene contenido retornará una tupla así:
    NOTICE: (pedro,210,"calle 1",2001-03-12)
  • Si no tiene retornará <NULL>
    NOTICE: <NULL>


.
Puedes verlas como variables que puedes usar como quieras para extraer la información nueva y antigua, por ejemplo se me ocurre que OLD puede ser útil para insertar en una nueva tabla los datos que acabas de actualizar o de borrar, así puedes tener como un historial de lo que hubo anterior mente en esa fila.

Recuerda que puedes acceder a la información de una columna especifica de esta forma:
OLD.name O NEW.home_address.

Si quieres hacer el mismo ejercicio solo debes poner en la Trigger function algo como esto:

  RAISE NOTICE '% % %', OLD.id, OLD.name, OLD.home_address;
  RAISE NOTICE '%', OLD;
  RAISE NOTICE '%', NEW;

Este tema de de bastante estudio

Como forma de enseñanza me parece perfecto el aprendizaje de los Triggers, siento que faltó mencionar que hacer Triggers es una mala práctica y no debería usarse. Excepto para casos muy especiales.

CREATE trigger miborratrigger
	AFTER DELETE
	on public.pasajero
	FOR EACH ROW
	EXECUTE PROCEDURE public.pasajeropl();

--EL RETO DE BORRADO

CREATE OR REPLACE FUNCTION public.impl_delete()
RETURNS TRIGGER
LANGUAGE 'plpgsql’
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
rec record;
contador integer := 0;
BEGIN
FOR rec IN SELECT * FROM pasajero LOOP
contador := contador + 1;
END LOOP;
INSERT INTO conteo_pasajero (total_pasajeros, tiempo, movimiento) VALUES (contador, now(), ‘ELIMINACION’);

RETURN NEW;

END
$BODY$;

– Tuve que volver a crear la tabla “conteo_pasajeros”, pero agregando otro campo “movimiento” para identificar qué tipo de instrucción se realizó en la tabla “pasajero” (INSERT o DELETE).

–Después volví a crear otra función para cada tipo de movimiento (no se me ocurrió otra forma de hacerlo por el momento) y a la vez volví a crear otros TRIGGERS para cada tipo de movimiento.

CREATE TRIGGER mitrigger_delete
AFTER DELETE
ON pasajero
FOR EACH ROW
EXECUTE PROCEDURE impl_delete();

–Esta forma de identificar qué tipo de movimiento se realiza me parece práctico para este tipo de procesos, de la misma forma se puede crear otro TRIGGER para UPDATE.

Si soluci[on fue reciclar la misma function y ejecutarla pero esta vez after delete:

CREATE TRIGGER my_trigger_delete
    AFTER DELETE
    ON public.passenger
    FOR EACH ROW
    EXECUTE FUNCTION public.pl_for_trigger();

Estuve pensando un rato como hacer que me arroje los datos insertados o eliminados al disparar el trigger y no me salio.
ALGUNA IDEA??

Cuando creo la función con el query editor todo bien, pero cuando quiero crearla con pg admin el único lenguaje que me aparece es SQL. No me da la opción de seleccionar ni ingresar otro, alguno tiene idea por que será?

CREATE TRIGGER mitrigger_borrar
    AFTER DELETE
    ON public.pasajero
    FOR EACH ROW
    EXECUTE PROCEDURE public.impl();

Necesito una buena razón para no hacerlo desde el backend, son demasiados pasos, y creo que el mantenimiento un dolor de cabeza.

Muy buena explicación

CREATE TRIGGER pruebatrigger
AFTER DELETE
ON pasajero
FOR EACH ROW
EXECUTE PROCEDURE pruebapl3();

CREATE TRIGGER name_trigger AFTER name_event ON name_table FOR EACH ROW EXECUTE PROCEDURE name_procedure;

FOR EACH ROW EACH ROW EXECUTE PROCEDURE indica que es para registro o fila de nuestra tabla

Mi trigger:

![](

CREATE TRIGGER trdel_pasajero
AFTER DELETE
ON public.pasajero
FOR EACH ROW
EXECUTE PROCEDURE public.importantepl();

Queda así el trigger. 😃

CREATE TRIGGER mitrigger
    AFTER INSERT OR DELETE
    ON public.pasajeros
    FOR EACH ROW
    EXECUTE PROCEDURE public.importantepl();
CREATE TRIGGER cant_pasajero
AFTER DELETE 
ON public.pasajero
FOR EACH ROW
EXECUTE PROCEDURE public.pasajero_trigger();
CREATE TRIGGER del_trigger
    AFTER DELETE
    ON public.pasajero
    FOR EACH ROW
    EXECUTE PROCEDURE public.impl();```

La NOW()función devuelve la fecha y hora actuales. El tipo de retorno de la NOW()función es la marca de tiempo con zona horaria

Triggers también conocido como disparadores estas nos permite ejecutar funciones dependiendo de acciones que ocurran sobre una tabla. Esas acciones pueden ser: Insert, Update, Delete

Cuando creamos una función de tipo trigger debemos retornar información al motor de bases de datos para confirmar los cambios. Los triggers tienen dos objetos importantes para retornar: old y new

La función tipo triggers debe retornar los valores OLD acepta lo viejo o NEW acepta lo nuevo. Sí se retorna VOID en nuestra función de tipo triggers no aceptamos cambios. Tando NEW como OLD son un objeto de tipo record y contiene dentro de si el registro.

TAREA:

CREATE TRIGGER nombre_trigger
AFTER DELETE
ON pasajero
FOR EACH ROW
EXECUTE PROCEDURE nombre_funcionPL();

CREATE TRIGGER name_trigger AFTER name_event ON name_table ; al crearlo este recibe tres parámetros para llamar la ejecución del trigger, estos son: BEFORE = antes, AFTER=luego, INSTEAD OF = hacer esto, en vez de lo que iba a hacer el motor de bases de datos.

<CREATE TRIGGER mitrigger2
    AFTER DELETE
    ON pasajeros
    FOR EACH ROW
    EXECUTE PROCEDURE imporpl();>

El trigger fue:

CREATE TRIGGER mi_nuevo_trigger
    AFTER INSERT OR DELETE
    ON public.pasajero
    FOR EACH ROW
    EXECUTE PROCEDURE public.funcion_trigger();

Hola a todos, cree el TRIGGER:

CREATE TRIGGER mitrigger2
AFTER DELETE
ON passenger
FOR EACH ROW
EXECUTE PROCEDURE testpl2();

y sus resultados fueron efectivos una vez realice un borrado simple y masivo de los últimos 5 ID’s registrados:

Aquí dejo mi ejercicio:

CREATE TRIGGER triggerDelete
AFTER DELETE
ON pasajero
FOR EACH ROW
EXECUTE PROCEDURE impl();

Un poco complejo,pero muy utiles

Mi aporte, trigger para delete pasajero:

CREATE TRIGGER trigger_cont_pasajero_delete
	AFTER DELETE 
	ON public.pasajero
	FOR EACH ROW
	EXECUTE PROCEDURE public.cantidad_pasajeros_pl();

Triggers

INSERT INTO: para insertar los valores de una función en una tabla

RETURNS TRIGGER: para convertir la función en un Trigger

CREATE TRIGGER: Para crear un Trigger

CREATE OR REPLACE FUNCTION delete_trigger()
RETURNS trigger
AS 
$$
DECLARE
var1 integer := 0;
BEGIN
	var1 = (SELECT COUNT(passenger_id) FROM passenger);
	
	INSERT INTO log_delete (total, fecha_delete)
	VALUES (var1, now());

	RETURN NEW; -- Confirma el cambio (INSERT), al motor de DB 
END;
$$
LANGUAGE PLPGSQL;

Función Crear_Version

CREATE OR REPLACE FUNCTION crear_version()
	RETURNS trigger
	LANGUAGE 'plpgsql'
AS $$
BEGIN
IF TG_OP = 'UPDATE' THEN
INSERT INTO versiones(version)
VALUES (now); 
END IF;
RETURN NEW; 
END;
$$

Trigger para UPDATE

CREATE TRIGGER actualización_version_tren
AFTER UPDATE
ON tren
FOR EACH ROW
EXECUTE PROCEDURE crear_version();

La idea triggers es actulizar una tabla de la base de datos dependiendo de la necesidas mientras aplicamos opecaiones insert, update o delete