【发布时间】:2021-04-23 13:30:12
【问题描述】:
在PostgreSQL 13.2 我有一个包含 5 个字段的表:id、val1、val2、val3、update_origin。
第 1 步:当创建或更新“val1”或“val2”时,触发器会生成“val3”。此触发器还使用“触发器更新”值更新字段“update_origin”。
第 2 步:用户也可以直接创建或更新 val3,如果是这样,我创建一个触发器,用“用户更新”值更新字段“update_origin”。
使用此设置,自动触发更新和手动用户更新之间没有区别,因为无法识别更新的来源(第二步始终正确,因为PostgreSQL 更新就是更新)。
如何区分来自触发器(第 1 步示例)或来自用户(第 2 步示例)的更新?
序列
CREATE SEQUENCE demo_id_seq
INCREMENT 1
START 1
MINVALUE 1
MAXVALUE 2147483647
CACHE 1;
表格
CREATE TABLE demo
(
id integer NOT NULL DEFAULT nextval('demo_id_seq'::regclass),
val1 character varying COLLATE pg_catalog."default",
val2 character varying COLLATE pg_catalog."default",
val3 character varying COLLATE pg_catalog."default",
update_origin character varying COLLATE pg_catalog."default"
)
TABLESPACE pg_default;
功能#1
CREATE FUNCTION val3_concat()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
BEGIN
UPDATE demo
SET val3 = CONCAT(val1, ' ', val2),
update_origin = 'trigger update'
WHERE id = currval('demo_id_seq');
RETURN null;
END
$BODY$;
触发器 #1
CREATE TRIGGER trigger_val3_concat
AFTER INSERT OR UPDATE OF val1, val2
ON demo
FOR EACH ROW
EXECUTE PROCEDURE val3_concat();
功能#2
CREATE FUNCTION update_origin()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
BEGIN
IF OLD.val3 <> NEW.val3 THEN
UPDATE demo
SET update_origin = 'user update'
WHERE id = currval('demo_id_seq');
END IF;
RETURN NEW;
END
$BODY$;
触发器 #2
CREATE TRIGGER trigger_update_origin
AFTER UPDATE OF val3
ON demo
FOR EACH ROW
EXECUTE PROCEDURE update_origin();
INSERT INTO demo (val1, val2) VALUES ('first', 'shot'); 表的示例将返回 1, first, shot, first shot, trigger update。
如果我更新 'val1' 或 val2' 表将返回 1, first, shot, first shot, user update 或者我希望只有当我更新 'val3' 并且只有 'val3' 时才会这样。
【问题讨论】:
-
触发器中不需要使用UPDATE。使用
BEFORE触发器并分配您想要的值:new.update_origin := 'trigger update'; -
如果我们知道为什么您需要能够区分差异,也许会有答案。
-
制作函数
BEFORE UPDATE并测试val3的值。如果OLD.val3 IS DISTINCT FROM NEW.val3则用户在使用该功能之前对其进行了更改。基于此,将update_origin设置为user_update。否则让函数生成val3并将update_origin设置为trigger_update。 -
@LaurenzAlbe 我的上下文:我需要知道在创建或更新“val1”或“val2”时触发器是否生成“val3”,或者用户是否手动创建或更新“val3” .这是为了可追溯性。
标签: postgresql triggers