sql >> Base de Datos >  >> RDS >> PostgreSQL

No hacer nada en un procedimiento desencadenante

Tu ejemplo está roto. El origen y el destino son los mismos en tu INSERT en el activador, que está obligado a generar una infracción única cada vez (excepto cuando se inserta NULL) - suprimido por ON CONFLICT (test_name2) DO NOTHING , por lo que nunca pasa nada en el activador.

También te olvidas de la restricción única en tu INSERT original . Ver más abajo.

INSERT INTO test2(test_name2)
   VALUES(NEW.test_name2)

...

CREATE TRIGGER trigger_test
AFTER INSERT
ON test2

Comience con una configuración menos confusa:

CREATE TABLE test1 (col1 text UNIQUE);
CREATE TABLE test2 (col2 text UNIQUE);

Y es más eficiente mover pg_trigger_depth() al gatillo mismo. Entonces esto funcionaría, copiando filas insertadas en test1 a test2 (y no al revés), solo para los primeros nivel de profundidad de activación:

CREATE OR REPLACE FUNCTION trig_test()
  RETURNS trigger AS
$func$
BEGIN
   INSERT INTO test2(col2)             -- !!
   VALUES (NEW.col1)                   -- !!
   ON     CONFLICT (col2) DO NOTHING;  -- !!

   RETURN NULL;
END
$func$ LANGUAGE plpgsql;

Lo guardé como AFTER generar. Puede ser un BEFORE disparador también, pero allí necesitarías RETURN NEW; .

CREATE TRIGGER trigger_test
AFTER INSERT ON test1                  -- !!
FOR EACH ROW 
WHEN (pg_trigger_depth() < 1)          -- !!
EXECUTE PROCEDURE trig_test();

Por qué (pg_trigger_depth() < 1) ?

Nota que atrape infracciones únicas en test2 de esta manera (no pasa nada), pero infracciones únicas en test1 aún generaría una excepción a menos que tenga ON CONFLICT ... DO NOTHING ahí también. Tu prueba es una ilusión:

Tiene que ser:

INSERT INTO test1 values ('test') ON CONFLICT (col1) DO NOTHING;

Alternativa:Cadena dos INSERT con un CTE

Si tiene control sobre INSERT comandos en test1 , puede hacer esto en lugar del disparador:

WITH ins1 AS (
   INSERT INTO test1(col1)
   VALUES ('foo')                  -- your value goes here
   ON CONFLICT (col1) DO NOTHING
   RETURNING *
   )
INSERT INTO test2(col2)
SELECT col1 FROM ins1
ON CONFLICT (col2) DO NOTHING;

Relacionado: