我有以下表格。
tbl_groups 包含所有当前数据,并且在更改时我将名称存储在历史记录表中。
CREATE TABLE tbl_groups (
id integer NOT NULL,
name varchar NOT NULL,
active boolean NOT NULL
);
CREATE TABLE tbl_groups_history (
id integer NOT NULL,
group_id integer NOT NULL,
name varchar NOT NULL
);
当活动字段为false时,可能不会发生更新。所以我为此创建了一个触发器,以便在发生这种情况时抛出异常:
CREATE OR REPLACE FUNCTION fn_group_deny_update_when_inactive() RETURNS TRIGGER AS
$BODY$
BEGIN
IF
OLD.active = false
THEN
RAISE EXCEPTION 'Record is inactive';
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;
CREATE TRIGGER 01_group_can_update
BEFORE UPDATE ON tbl_groups
FOR EACH ROW
EXECUTE PROCEDURE fn_group_deny_update_when_inactive();
我还有一个将记录写入历史记录表的触发器
CREATE OR REPLACE FUNCTION fn_group_log_history() RETURNS trigger as
$BODY$
BEGIN
IF
(NEW.name <> OLD.name)
THEN
INSERT INTO tbl_groups_history (group_id, name)
VALUES (OLD.id, OLD.name);
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;
CREATE TRIGGER 02_group_write_history_log
BEFORE UPDATE ON tbl_groups
FOR EACH ROW
EXECUTE PROCEDURE fn_group_log_history();
我已将01和02命名为触发器作为前缀,因此我知道它们将以什么顺序执行,因为PostgreSQL按字母顺序触发它们。
我对这种方法有一些疑问,因为我不确定这是不是很好的做法:
一切功能:
CREATE OR REPLACE FUNCTION fn_group_before_update() RETURNS trigger as
$BODY$
BEGIN
IF
OLD.active = false
THEN
RAISE EXCEPTION 'Record is inactive';
END IF;
IF
(NEW.name <> OLD.name)
THEN
INSERT INTO tbl_groups_history (group_id, name)
VALUES (OLD.id, OLD.name);
END IF;
RETURN NEW;
END;
$BODY$
考虑到性能,代码维护以及类似内容的任何想法?
答案 0 :(得分:2)
两个问题。 01_group_can_update
不是一个正确的名称,因此请更改为例如:
CREATE TRIGGER trg_01_group_can_update
BEFORE UPDATE ON tbl_groups
FOR EACH ROW
EXECUTE PROCEDURE fn_group_deny_update_when_inactive();
接下来,id
中的tbl_groups_history
应为序列号:
CREATE TABLE tbl_groups_history (
id serial NOT NULL,
group_id integer NOT NULL,
name varchar NOT NULL
);
没有理由在你的情况下有多个触发器,所以第二个解决方案似乎更好。但是,第一个变体也应该起作用。每the documentation:
如果为同一关系上的同一事件定义了多个触发器,则触发器名称将按字母顺序触发。在BEFORE和INSTEAD OF触发器的情况下,每个触发器返回的可能修改的行成为下一个触发器的输入。如果任何BEFORE或INSTEAD OF触发器返回NULL,则该行的操作将被放弃,并且不会触发后续触发器(对于该行)。