CREATE OR REPLACE FUNCTION verificar_pagina_inicial_final() RETURNS trigger AS $BODY$ BEGIN IF NEW.pg_inicial < NEW.pg_final THEN INSERT INTO artigos(id_artigo,id_editora,tipo_artigo,pg_inicial,pg_final) VALUES(NEW.id_artigo,NEW.id_editora,NEW.tipo_artigo,NEW.pg_inicial,NEW.pg_final); END IF; END; $BODY$ LANGUAGE plpgsql; CREATE TRIGGER verifiar_paginas_novo_artigo BEFORE INSERT OR UPDATE ON artigos FOR EACH ROW EXECUTE PROCEDURE verificar_pagina_inicial_final();Cuando intento insertar me devuelve esto:
INSERT INTO public.artigos(id_artigo, id_editora, tipo_artigo, pg_inicial, pg_final) VALUES (30, 3, 'teste', 1, 2);Devoluciones:
ERROR: stack depth limit exceeded HINT: Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate. CONTEXT: SQL statement "INSERT INTO artigos(id_artigo,id_editora,tipo_artigo,pg_inicial,pg_final) VALUES(NEW.id_artigo,NEW.id_editora,NEW.tipo_artigo,NEW.pg_inicial,NEW.pg_final)" PL/pgSQL function verificar_pagina_inicial_final() line 4 at SQL statement
Su activador inserta la misma fila una y otra vez. Hay varias maneras de prevenir esto. Me gusta:
CREATE TRIGGER verifiar_paginas_novo_artigo BEFORE INSERT OR UPDATE ON artigos FOR EACH ROW WHEN (pg_trigger_depth() < 1) -- ! EXECUTE FUNCTION verificar_pagina_inicial_final();Ver:
EXECUTE FUNCTION requiere Postgres 11. Ver:
Pero parece que solo quieres deshabilitar pg_inicial >= pg_final . Podrías hacer eso con una restricción CHECK :
ALTER TABLE artigos ADD CONSTRAINT pg_final_must_be_greater_than_pg_inicial CHECK (pg_inicial < pg_final); Una restricción CHECK es más simple, más rápida y más confiable. Ver:
Genera una excepción cuando se viola, por supuesto, que normalmente es el camino a seguir.
Para hacerlo en silencio, vuelves a los disparadores. Simplemente más simple:
CREATE OR REPLACE FUNCTION verificar_pagina_inicial_final() RETURNS trigger LANGUAGE plpgsql AS $func$ BEGIN IF NEW.pg_inicial < NEW.pg_final THEN RETURN NEW; -- proceed ELSE RETURN NULL; -- skip insert / update END IF; END $func$; Para proceder normalmente con un INSERT / UPDATE , un disparador BEFORE debe RETURN NEW; . RETURN NULL cancela la fila.
Suponiendo que esto es solo una prueba antes de una inserción, ya que no modifica los datos, tal vez
IF (NEW.pg_inicial < NEW.pg_final) THEN RETURN NEW; ELSE RETURN NULL; END IF;pd: haré un violín DB para verificar si esta sintaxis está bien. aquí está el violín, https://www.db-fiddle.com/f/9iDx4bmJdk5rUzPrFdevAt/2 .
Edit2: la respuesta de Erwin Brandstetter está completa, debe agregar una restricción en lugar de este activador.
Dado que está "insertando" solo columnas nuevas, la inserción, en la función de activación, es completamente innecesaria; eso es lo que se insertará de todos modos. La pregunta se convierte en qué quieres, entonces IF NEW.pg_inicial < NEW.pg_final" devuelve Falso. Tienes básicamente 3 opciones:
Los disparadores de nivel de fila activados ANTES pueden devolver un valor nulo para señalar al administrador de activadores que se salte el resto de la operación para esta fila (es decir, los activadores subsiguientes no se activan y INSERTAR/ACTUALIZAR/ELIMINAR no se produce para esta fila).
En el que implementar la función de disparo de la siguiente manera:
create or replace function verificar_pagina_inicial_final() returns trigger language plpgsql as $$ begin if new.pg_inicial < new.pg_final then return new; else return null; end if; end; $$ ;