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:
- Infoga data i 3 tabeller åt gången med Postgres
- PostgreSQL multi INSERT. ..ÅTERKOMMANDE med flera kolumner