Dit eksempel er brudt. Kilde og mål er de samme i din INSERT
i udløseren, hvilket er bundet til at rejse en unik overtrædelse hver gang (undtagen ved indsættelse af NULL) - undertrykt af ON CONFLICT (test_name2) DO NOTHING
, så der sker aldrig noget i aftrækkeren.
Du glemmer også den unikke begrænsning i din originale INSERT
. Se nedenfor.
INSERT INTO test2(test_name2)
VALUES(NEW.test_name2)
...
CREATE TRIGGER trigger_test
AFTER INSERT
ON test2
Start med en mindre forvirrende opsætning:
CREATE TABLE test1 (col1 text UNIQUE);
CREATE TABLE test2 (col2 text UNIQUE);
Og det er mere effektivt at flytte pg_trigger_depth()
til selve udløseren. Så dette ville fungere, kopiering af rækker indsat i test1
til test2
(og ikke omvendt), kun for den første niveau af triggerdybde:
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;
Jeg beholdt det som AFTER
udløser. Kan være en BEFORE
trigger også, men der skal du bruge RETURN NEW;
.
CREATE TRIGGER trigger_test
AFTER INSERT ON test1 -- !!
FOR EACH ROW
WHEN (pg_trigger_depth() < 1) -- !!
EXECUTE PROCEDURE trig_test();
Hvorfor (pg_trigger_depth() < 1)
?
Bemærk at du fanger unikke overtrædelser i test2
denne måde (der sker intet), men unikke overtrædelser i test1
ville stadig rejse en undtagelse, medmindre du har ON CONFLICT ... DO NOTHING
der også. Din test er ønsketænkning:
Skal være:
INSERT INTO test1 values ('test') ON CONFLICT (col1) DO NOTHING;
Alternativ:Kæde to INSERT
med en CTE
Hvis du har kontrol over INSERT
kommandoer på test1
, kan du gøre dette i stedet for triggeren:
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;
Relateret:
- Indsæt data i 3 tabeller ad gangen ved hjælp af Postgres
- PostgreSQL multi INSERT. ..RETURNERING med flere kolonner