当修改/删除一行时,我正在处理数据库的历史记录。 我的主表是“ bati”,历史表是“ bati_history”,当删除或修改一行时,触发器应该将所有旧数据插入到bati_history中,然后在主表(bati)中删除。但是使用我的代码,该行将插入到历史记录中,但不会在主表中删除,并且我不知道为什么。
我使用的是PostgreSQL 11.2 64位
代码:
主表:
CREATE TABLE IF NOT EXISTS bati(
id_bati BIGSERIAL NOT NULL UNIQUE,
code_bati VARCHAR(25) NOT NULL,
code_parcelle CHAR(50) NOT NULL,
...);
历史记录表:
CREATE TABLE IF NOT EXISTS bati_history(
id_history BIGSERIAL NOT NULL PRIMARY KEY,
event CHAR(10) NOT NULL,
date_save_history TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
id_bati BIGINT NOT NULL,
code_bati VARCHAR(25) NOT NULL,
code_parcelle CHAR(50) NOT NULL,
...);
功能
CREATE FUNCTION archive_bati() RETURNS TRIGGER AS $BODY$
BEGIN
IF (TG_OP = 'DELETE') THEN
INSERT INTO bati_history (event,id_bati,code_bati,code_parcelle,...)
VALUES ('DELETE',OLD.id_bati,OLD.code_bati,OLD.code_parcelle,OLD....);
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO bati_history (event,id_bati,code_bati,code_parcelle,...)
VALUES ('UPDATE',OLD.id_bati,OLD.code_bati,OLD.code_parcelle,OLD....);
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql';
触发器:
CREATE TRIGGER bati_trigger_before_delete BEFORE DELETE
ON bati FOR EACH ROW
EXECUTE PROCEDURE archive_bati();
CREATE TRIGGER bati_trigger_before_update BEFORE UPDATE
ON bati FOR EACH ROW
EXECUTE PROCEDURE archive_bati();
当我尝试DELETE FROM bati;
时,我希望复制bati_history中的每一行,然后将其从bati中删除,但是它们并不是从bati中删除,因此我的输出没有错误:
test=# INSERT INTO bati (id_bati,code_bati,code_parcelle,id_interne) VALUES (5,'CODEBATI001','CODEPARC001',02);
INSERT 0 1
test=# INSERT INTO bati (id_bati,code_bati,code_parcelle,id_interne) VALUES (6,'CODEBATI002','CODEPARC002',02);
INSERT 0 1
test=# DELETE FROM bati;
DELETE 0
(抱歉我的英语是法语)
答案 0 :(得分:2)
根据触发操作,应使用if-else
分支返回NEW
或OLD
。变量TG_OP
具有文本类型&可以直接在插入查询中使用。
因此,函数定义变为:
CREATE FUNCTION archive_bati()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO bati_history (event,id_bati,code_bati,code_parcelle)
VALUES (TG_OP, OLD.id_bati, OLD.code_bati, OLD.code_parcelle);
IF TG_OP = 'DELETE'
THEN RETURN OLD;
ELSE RETURN NEW;
END IF;
END;
$$ LANGUAGE PLPGSQL;
另外,对于我来说似乎没有必要在1满足时定义两个触发器:
CREATE TRIGGER bati_trigger_before_update BEFORE UPDATE OR DELETE
ON bati FOR EACH ROW
EXECUTE PROCEDURE archive_bati();
答案 1 :(得分:1)
删除行时,NEW
为空。如果before
触发器返回null,则意味着应取消该操作。然后,您应该返回OLD
进行删除,并返回NEW
进行更新。
来自doc:
对于DELETE上的触发器,返回值不包含 直接效果,但必须为非null才能使触发操作 继续。请注意,DELETE触发器中的NEW为null,因此返回 通常是不明智的。 DELETE触发器中通常的习惯用法是 返回OLD。