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:
- Insertar datos en 3 tablas a la vez usando Postgres
- PostgreSQL multi INSERT. ..REGRESANDO con múltiples columnas