首页 > 解决方案 > 在插入或更新之前触发一次或两次?

问题描述

我创建了以下触发器;

CREATE TRIGGER material_trigger
    BEFORE INSERT OR UPDATE ON materials
    FOR EACH ROW
    EXECUTE PROCEDURE my_proc ();

我很难理解何时my_proc将在 upsert 查询上运行,如下所示:

--UPSERT
INSERT INTO materials (id, col)
VALUES (1, 1)
ON CONFLICT (id) DO UPDATE SET
col='x'

如果我正在运行 upsert,我是否正确地认为:

然后从逻辑上讲,如果我运行这个AFTERupsert 我会确保my_proc只触发一次?

标签: postgresqltriggerssql-updatesql-insert

解决方案


在执行的情况下,触发器实际上被触发了两次UPDATE。这可以使用以下方法来证明:

-- create table
CREATE TABLE IF NOT EXISTS example (uuid int unique);
-- create function
CREATE OR REPLACE FUNCTION print_function ()
    RETURNS TRIGGER
    AS $body$
    BEGIN
    RAISE NOTICE 'Starting';
    RAISE NOTICE 'METHOD: %' , TG_OP;
    RETURN NEW;
    END;
    
    $body$
    LANGUAGE plpgsql;
-- create trigger function
CREATE TRIGGER example_trigger
    BEFORE INSERT OR UPDATE ON example
    FOR EACH ROW
    EXECUTE PROCEDURE print_function ();
--  upserts
INSERT INTO example(uuid) VALUES (1) ON CONFLICT(uuid) DO UPDATE SET uuid=5;
INSERT INTO example(uuid) VALUES (1) ON CONFLICT(uuid) DO UPDATE SET uuid=5;

这给出了输出:

NOTICE:  Starting
NOTICE:  METHOD: INSERT             -- Populated with inital value
NOTICE:  Starting
NOTICE:  METHOD: INSERT             -- Fired a first time for insert (can't insert as exists)
NOTICE:  Starting
NOTICE:  METHOD: UPDATE             -- Fired a second time for update
INSERT 0 1

推荐阅读