PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Не правете нищо в процедура за задействане

Вашият пример е счупен. Източникът и целта са еднакви във вашия INSERT в тригера, който е длъжен да предизвика уникално нарушение всеки път (освен при вмъкване на NULL) - потиска се от ON CONFLICT (test_name2) DO NOTHING , така че никога нищо не се случва в тригера.

Също така забравяте за уникалното ограничение във вашия оригинален INSERT . Вижте по-долу.

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

...

CREATE TRIGGER trigger_test
AFTER INSERT
ON test2

Започнете с по-малко объркваща настройка:

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

И е по-ефективно да преместите pg_trigger_depth() към самия спусък. Така че това ще работи, копиране на редове, вмъкнати в test1 към test2 (а не обратното), само за първия ниво на дълбочина на задействане:

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;

Запазих го като AFTER спусък. Може да бъде BEFORE задействане, но там ще имате нужда RETURN NEW; .

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

Защо (pg_trigger_depth() < 1) ?

Забележка че прихващате уникални нарушения в test2 по този начин (нищо не се случва), но уникални нарушения в test1 пак ще повдигне изключение, освен ако нямате ON CONFLICT ... DO NOTHING там също. Вашият тест е пожелателно мислене:

Трябва да бъде:

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

Алтернатива:Верига две INSERT с CTE

Ако имате контрол над INSERT команди на test1 , можете да направите това вместо тригера:

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;

Свързани:




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Регистрирайте и стартирайте PostgreSQL 9.0 като Windows Service

  2. Името на таблица или колона не може да започва с число?

  3. Шаблони и модификатори за числово форматиране в PostgreSQL

  4. Свързване с база данни PostgreSQL чрез SSH тунелиране в Python

  5. PostgreSQL psql команден ред показва колона bytea