Quedé en la nebulosa con esta lección.
Configurar Postgres
Qué aprenderás sobre PostgreSQL
¿Qué es Postgresql?
Instalación y configuración de la Base de Datos
Interacción con Postgres desde la Consola
PgAdmin: Interacción con Postgres desde la Interfaz Gráfica
Archivos de Configuración
Comandos más utilizados en PostgreSQL
Presentación del Proyecto
Tipos de datos
Diseñando nuestra base de datos: estructura de las tablas
Jerarquía de Bases de Datos
Gestión de la información en bases de datos
Creación de Tablas
Particiones
Creación de Roles
Llaves foráneas
Inserción y consulta de datos
Inserción masiva de datos
Generar consultas avanzadas
Cruzar tablas: SQL JOIN
Funciones Especiales Principales
Funciones Especiales Avanzadas
Vistas
PL/SQL
Triggers
Integrar bases de datos con servicios externos
Simulando una conexión a Bases de Datos remotas
Transacciones
Otras Extensiones para Postgres
Implementar mejores prácticas
Backups y Restauración
Mantenimiento
Introducción a Réplicas
Implementación de Réplicas en Postgres
Otras buenas prácticas
Cierre del curso
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Aportes 121
Preguntas 10
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:
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’
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;
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.
CREATE TRIGGER name_trigger name_event ON name_table FOR EACH ROW EXECUTE PROCEDURE name_procedure;
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.
-- 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
 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:
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
Dejo por aquí la documentación: https://www.postgresql.org/docs/9.1/sql-createtrigger.html
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:
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;
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:
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 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:
NOTICE: (pedro,210,"calle 1",2001-03-12)
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:
;
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
Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.