postgresql - 在插入或更新之前触发一次或两次?
问题描述
我创建了以下触发器;
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,我是否正确地认为:
- 在的情况下,
INSERT
它将运行一次 - 在 a 的情况下,
UPDATE
它将运行两次
然后从逻辑上讲,如果我运行这个AFTER
upsert 我会确保my_proc
只触发一次?
解决方案
在执行的情况下,触发器实际上被触发了两次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
推荐阅读
- python - 除缩写外的正则表达式清理
- javascript - 为 React Router 使用单例是否安全?
- javascript - 执行 eslint 时找不到模块“json-schema”错误
- node.js - NodeJs .env 文件中的 Linux 环境变量
- ajax - 如何使用laravel响应成功下载ajax文件
- python - 在 python 中快速重新投影空间数据
- c# - Entity Framework Core 通过数据本身改变 fk
- javascript - 音乐播放器仅从一个文件夹播放
- javascript - 带有弹出框的动画
- javascript - 反应应用程序:所有三个按钮都被自己点击,我如何阻止这种情况发生(反应非常新)