PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Nichts tun in einer Trigger-Prozedur

Dein Beispiel ist kaputt. Quelle und Ziel sind in Ihrem INSERT gleich im Auslöser, der zwangsläufig jedes Mal einen eindeutigen Verstoß auslösen wird (außer beim Einfügen von NULL) - unterdrückt durch ON CONFLICT (test_name2) DO NOTHING , sodass im Trigger niemals etwas passiert.

Sie vergessen auch die Eindeutigkeitsbeschränkung in Ihrem ursprünglichen INSERT . Siehe unten.

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

...

CREATE TRIGGER trigger_test
AFTER INSERT
ON test2

Beginnen Sie mit einem weniger verwirrenden Setup:

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

Und es ist effizienter, pg_trigger_depth() zum Auslöser selbst. Das würde also funktionieren, indem Zeilen kopiert werden, die in test1 eingefügt wurden zu test2 (und nicht umgekehrt), nur für das erste Level der Triggertiefe:

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;

Ich habe es als AFTER beibehalten Abzug. Kann ein BEFORE sein Trigger auch, aber dort würden Sie brauchen RETURN NEW; .

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

Warum (pg_trigger_depth() <1) ?

Hinweis dass Sie eindeutige Verstöße in test2 abfangen auf diese Weise (es passiert nichts), aber eindeutige Verletzungen in test1 würde immer noch eine Ausnahme auslösen, es sei denn, Sie haben ON CONFLICT ... DO NOTHING dort genauso. Ihr Test ist Wunschdenken:

Muss sein:

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

Alternative:Zwei INSERT verketten mit einem CTE

Wenn Sie die Kontrolle über INSERT haben Befehle auf test1 , können Sie dies anstelle des Triggers tun:

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;

Verwandte: