I have a pretty simple trigger:
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();
My table logs is the following:
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)
);
After inserting something in dateien I get the following error:
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
Why did I get this error? I looked into the documentation and it seems they use new in the same way I do.
From the fine manual:
And from Trigger Procedures:
Note what it says about row-level triggers and statement-level triggers.
You have a statement-level trigger:
Statement-level triggers are triggered once per statement and a statement can apply to multiple rows so the notion of affected row (which is what
NEWandOLDare about) simply doesn’t apply.If you want to use
NEW(orOLD) in a trigger then you want the trigger to execute for each affected row and that means you want a row-level trigger:I just changed
FOR EACH STATEMENTtoFOR EACH ROW.Your trigger should also be returning something:
So you should
RETURN NEW;orRETURN NULL;in your trigger. You have an AFTER trigger so it doesn’t matter which RETURN you use but I’d go withRETURN NEW;.