Sql 插入访问新文件后的Postgres触发器

Sql 插入访问新文件后的Postgres触发器,sql,postgresql,triggers,plpgsql,Sql,Postgresql,Triggers,Plpgsql,我有一个非常简单的触发器: CREATE OR REPLACE FUNCTION f_log_datei() RETURNS TRIGGER AS $$ BEGIN INSERT INTO logs (aktion, tabelle, benutzer_id) VALUES(TG_OP, 'dateien', NEW.benutzer_id); END; $$ LANGUAGE 'plpgsql'; CREATE TRIGGER log_datei AFTER INSERT OR UPDA

我有一个非常简单的触发器:

CREATE OR REPLACE FUNCTION f_log_datei()
RETURNS TRIGGER AS $$
BEGIN
  INSERT INTO logs (aktion, tabelle, benutzer_id) VALUES(TG_OP, 'dateien', NEW.benutzer_id);
END; $$ LANGUAGE 'plpgsql';

CREATE TRIGGER log_datei AFTER INSERT OR UPDATE OR DELETE
ON dateien
FOR EACH STATEMENT
EXECUTE PROCEDURE f_log_datei();
我的表日志如下所示:

CREATE TABLE logs(
    id int PRIMARY KEY DEFAULT NEXTVAL('logs_id_seq'),
    zeit timestamp DEFAULT now(),
    aktion char(6),
    tabelle varchar(32),
    alt varchar(256),
    neu varchar(256),
    benutzer_id int references benutzer(id)
);
在dateien中插入某些内容后,出现以下错误:

ERROR:  record "new" is not assigned yet
DETAIL:  The tuple structure of a not-yet-assigned record is indeterminate.
CONTEXT:  SQL statement "INSERT INTO logs (aktion, tabelle, benutzer_id) VALUES(TG_OP, 'dateien', NEW.benutzer_id)"
PL/pgSQL function "f_log_datei" line 3 at SQL statement
为什么我会犯这个错误?我查看了文档,发现它们似乎以与我相同的方式使用了new。

来自:

36.1。触发器行为概述
[…]
对于行级触发器,输入数据还包括
INSERT
UPDATE
触发器的
NEW
行,和/或
UPDATE
DELETE
触发器的
OLD
行。语句级触发器当前无法检查由语句修改的各行

和来自:

新建

数据类型
记录
;为行级触发器中的
插入
/
更新
操作保存新数据库行的变量。该变量在语句级触发器和
DELETE
操作中为
NULL

请注意它对行级触发器和语句级触发器的说明

您有一个语句级触发器:

...
FOR EACH STATEMENT
EXECUTE PROCEDURE f_log_datei();
CREATE TRIGGER log_datei AFTER INSERT OR UPDATE OR DELETE
ON dateien
FOR EACH ROW
EXECUTE PROCEDURE f_log_datei();
每个语句都会触发一次语句级触发器,并且一个语句可以应用于多行,因此受影响行的概念(即
NEW
OLD
的含义)根本不适用

如果要在触发器中使用
NEW
(或
OLD
),则需要为每个受影响的行执行触发器,这意味着您需要行级触发器:

...
FOR EACH STATEMENT
EXECUTE PROCEDURE f_log_datei();
CREATE TRIGGER log_datei AFTER INSERT OR UPDATE OR DELETE
ON dateien
FOR EACH ROW
EXECUTE PROCEDURE f_log_datei();
我刚刚将每条语句的
更改为每行的


您的触发器还应:

触发器函数必须返回
NULL
或一个记录/行值,该记录/行值必须与触发触发器的表的结构完全相同。
[…]
始终忽略在
之后触发的
行级触发器或在
之前或之后触发的
语句级触发器的返回值;它也可能是空的。但是,这些类型的触发器中的任何一种都可能通过引发错误而中止整个操作


所以你应该
返回新的
返回NULL在触发器中。您有一个AFTER触发器,所以使用哪个返回并不重要,但我会选择
returnnew

您是否也添加了
返回新代码到函数末尾?@kgrittn:那将是下一个bug,不是吗?但是,是的,我甚至没有看到,值得一提的是,我们在这里。是的,我添加了
RETURN
语句:)如果是在触发器之后,您应该使用
returnnull
。因为触发后没有效果。返回
NEW
充其量只是误导。