sql >> Databasteknik >  >> RDS >> PostgreSQL

Gör ingenting i en triggerprocedur

Ditt exempel är trasigt. Källa och mål är samma i din INSERT i utlösaren, vilket är skyldigt att skapa en unik överträdelse varje gång (förutom när du infogar NULL) - undertryckt av ON CONFLICT (test_name2) DO NOTHING , så ingenting händer någonsin i avtryckaren.

Du glömmer också bort den unika begränsningen i din ursprungliga INSERT . Se nedan.

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

...

CREATE TRIGGER trigger_test
AFTER INSERT
ON test2

Börja med en mindre förvirrande inställning:

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

Och det är mer effektivt att flytta pg_trigger_depth() till själva avtryckaren. Så det här skulle fungera, kopiera rader infogade i test1 till test2 (och inte åt andra hållet), bara för den första nivå av triggerdjup:

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;

Jag behöll den som AFTER utlösare. Kan vara en BEFORE trigger också, men där behöver du RETURN NEW; .

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

Varför (pg_trigger_depth() < 1) ?

Obs att du fångar unika överträdelser i test2 på detta sätt (ingenting händer), men unika överträdelser i test1 skulle fortfarande skapa ett undantag om du inte har ON CONFLICT ... DO NOTHING där också. Ditt test är önsketänkande:

Måste vara:

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

Alternativ:Kedja två INSERT med en CTE

Om du har kontroll över INSERT kommandon på test1 , kan du göra detta istället för utlösaren:

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;

Relaterat:




  1. hur gör man en trigger som primärnyckelbegränsning?

  2. SQLite Skapa tabell

  3. Slick 3.0 bulk infoga eller uppdatera (upsert)

  4. SQL Server prestanda råd från Brent Ozar och Pinal Dave