sql >> データベース >  >> RDS >> PostgreSQL

トリガー手順では何もしません

    あなたの例は壊れています。ソースとターゲットは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;
    

    関連:




    1. 手順には、テーブルに対する個別のアクセス権が必要ですか?

    2. PerlからMySQLストアドプロシージャを呼び出すにはどうすればよいですか?

    3. MySQLのIFステートメントの正しい構文は何ですか?

    4. SQL Serverトランザクションレプリケーションの内部–パート2