PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Nie rób nic w procedurze wyzwalania

Twój przykład jest zepsuty. Źródło i cel są takie same w INSERT w czynniku wyzwalającym, który z pewnością zgłosi unikalne naruszenie za każdym razem (z wyjątkiem wstawiania NULL) - pomijane przez ON CONFLICT (test_name2) DO NOTHING , więc nic się nie dzieje w wyzwalaczu.

Zapominasz także o unikalnym ograniczeniu w oryginalnym INSERT . Zobacz poniżej.

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

...

CREATE TRIGGER trigger_test
AFTER INSERT
ON test2

Zacznij od mniej skomplikowanej konfiguracji:

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

I bardziej wydajne jest przeniesienie pg_trigger_depth() do samego spustu. Więc to zadziała, kopiując wiersze wstawione do test1 do test2 (a nie odwrotnie), tylko w pierwszym poziom głębokości wyzwalania:

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;

Zachowałem to jako AFTER cyngiel. Może być BEFORE również wyzwalacz, ale tam potrzebujesz RETURN NEW; .

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

Dlaczego (pg_trigger_depth() < 1) ?

Uwaga że wyłapujesz unikalne naruszenia w test2 w ten sposób (nic się nie dzieje), ale unikalne naruszenia w test1 nadal zgłosi wyjątek, chyba że masz ON CONFLICT ... DO NOTHING tam też. Twoim testem jest myślenie życzeniowe:

Musi być:

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

Alternatywnie:Połącz dwa INSERT z CTE

Jeśli masz kontrolę nad INSERT komendy na test1 , możesz to zrobić zamiast wyzwalacza:

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;

Powiązane:




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak napisać zapytanie Django, które wykonuje matematykę dat, gdy jest wykonywane jako PostGres SQL?

  2. Jak zaktualizować wiersze w bazie danych wartościami z data.frame w języku R warunkowo?

  3. Jak zapytać o sumę poprzedniego wiersza tej samej kolumny za pomocą pgSql

  4. Zaktualizuj zapytanie zbyt wolno w Postgresie 9.1

  5. Jak sprawdzić, czy komórka typu integer array zawiera określoną wartość w SQL?