PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Ne rien faire dans une procédure de déclenchement

Votre exemple est cassé. La source et la cible sont les mêmes dans votre INSERT dans le déclencheur, qui est lié à déclencher une violation unique à chaque fois (sauf lors de l'insertion de NULL) - supprimé par ON CONFLICT (test_name2) DO NOTHING , donc rien ne se passe jamais dans le déclencheur.

Vous oubliez également la contrainte unique dans votre INSERT d'origine . Voir ci-dessous.

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

...

CREATE TRIGGER trigger_test
AFTER INSERT
ON test2

Commencez par une configuration moins déroutante :

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

Et il est plus efficace de déplacer pg_trigger_depth() au déclencheur lui-même. Donc, cela fonctionnerait, en copiant les lignes insérées dans test1 à test2 (et non l'inverse), uniquement pour le premier niveau de profondeur de déclenchement :

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;

Je l'ai gardé comme AFTER gâchette. Peut être un BEFORE déclencher également, mais là, vous auriez besoin RETURN NEW; .

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

Pourquoi (pg_trigger_depth() < 1) ?

Remarque que vous interceptez des violations uniques dans test2 de cette façon (rien ne se passe), mais des violations uniques dans test1 soulèverait toujours une exception à moins que vous n'ayez ON CONFLICT ... DO NOTHING là aussi. Votre test est un vœu pieux :

Doit être :

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

Alternative :chaînez deux INSERT avec un CTE

Si vous contrôlez INSERT commandes sur test1 , vous pouvez le faire à la place du déclencheur :

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;

Connexe :