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 鈥榩lpgsql鈥

  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谩 鈥榩assenger_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 鈥渢rigger 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鈥e que esta de parte nuestra buscar mas informacion鈥reo 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 鈥榬ow鈥.
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(), 鈥楨LIMINACION鈥);

RETURN NEW;

END
$BODY$;

鈥 Tuve que volver a crear la tabla 鈥渃onteo_pasajeros鈥, pero agregando otro campo 鈥渕ovimiento鈥 para identificar qu茅 tipo de instrucci贸n se realiz贸 en la tabla 鈥減asajero鈥 (INSERT o DELETE).

鈥揇espu茅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();

鈥揈sta 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鈥檚 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