Váš příklad je nefunkční. Zdroj a cíl jsou ve vašem INSERT
stejné ve spouštěči, což nutně vyvolá jedinečné porušení pokaždé (kromě vložení NULL) - potlačeno pomocí ON CONFLICT (test_name2) DO NOTHING
, takže se ve spouštěči nikdy nic nestane.
Také zapomenete na jedinečné omezení ve svém původním INSERT
. Viz níže.
INSERT INTO test2(test_name2)
VALUES(NEW.test_name2)
...
CREATE TRIGGER trigger_test
AFTER INSERT
ON test2
Začněte s méně matoucím nastavením:
CREATE TABLE test1 (col1 text UNIQUE);
CREATE TABLE test2 (col2 text UNIQUE);
A je efektivnější přesunout pg_trigger_depth()
na samotnou spoušť. Takže by to fungovalo, kopírování řádků vložených do test1
na test2
(a ne naopak), pouze pro první úroveň hloubky spouštění:
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;
Nechal jsem to jako AFTER
spoušť. Může být BEFORE
spouště také, ale tam byste potřebovali RETURN NEW;
.
CREATE TRIGGER trigger_test
AFTER INSERT ON test1 -- !!
FOR EACH ROW
WHEN (pg_trigger_depth() < 1) -- !!
EXECUTE PROCEDURE trig_test();
Proč (pg_trigger_depth() < 1)
?
Poznámka že zachytíte jedinečná porušení v test2
tímto způsobem (nic se nestane), ale jedinečná porušení v test1
by stále vyvolalo výjimku, pokud nemáte ON CONFLICT ... DO NOTHING
tam také. Váš test je zbožné přání:
Musí být:
INSERT INTO test1 values ('test') ON CONFLICT (col1) DO NOTHING;
Alternativa:Řetězec dvě INSERT
s CTE
Pokud máte kontrolu nad INSERT
příkazy na test1
, můžete to udělat místo spouštěče:
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;
Související: