あなたの例は壊れています。ソースとターゲットはINSERT
で同じです トリガーで、毎回一意の違反が発生することになります (NULLを挿入する場合を除く)- ON CONFLICT(test_name2)DO NOTHING
によって抑制されます 、したがって、トリガーでは何も起こりません。
また、元の INSERT
の一意の制約についても忘れています。 。以下を参照してください。
INSERT INTO test2(test_name2)
VALUES(NEW.test_name2)
...
CREATE TRIGGER trigger_test
AFTER INSERT
ON test2
混乱の少ない設定から始めます:
CREATE TABLE test1 (col1 text UNIQUE);
CREATE TABLE test2 (col2 text UNIQUE);
また、<を移動する方が効率的です。 code> pg_trigger_depth()
トリガー自体に。したがって、これは機能し、 test1
に挿入された行をコピーします test2
へ (他の方法ではありません)、最初ののみ トリガー深度のレベル:
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;
AFTER
として保管しました 引き金。 BEFORE
にすることができます トリガーも同様ですが、必要 RETURN NEW;
。
CREATE TRIGGER trigger_test
AFTER INSERT ON test1 -- !!
FOR EACH ROW
WHEN (pg_trigger_depth() < 1) -- !!
EXECUTE PROCEDURE trig_test();
なぜ(pg_trigger_depth()<1)
?
注 test2
で一意の違反をトラップすること この方法(何も起こりません)ですが、 test1
での固有の違反 ON CONFLICT ... DO NOTHING
がない限り、例外が発生します。 そこにも。あなたのテストは希望的観測です:
する必要があります:
INSERT INTO test1 values ('test') ON CONFLICT (col1) DO NOTHING;
代替:チェーン2 INSERT
CTEを使用
INSERT
を制御できる場合 test1
のコマンド 、トリガーの代わりにこれを行うことができます:
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;
関連: