2012-06-12 29 views
15

Tôi có một cò khá đơn giản:Postgres kích hoạt sau khi chèn truy cập MỚI

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(); 

ghi bàn của tôi là như sau:

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) 
); 

Sau khi chèn một cái gì đó trong dateien tôi nhận được lỗi sau:

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 

Tại sao tôi gặp lỗi này? Tôi nhìn vào tài liệu và có vẻ như họ sử dụng mới theo cùng cách tôi làm.

Trả lời

33

Từ fine manual:

36.1. Overview of Trigger Behavior
[...]
For a row-level trigger, the input data also includes the NEW row for INSERT and UPDATE triggers, and/or the OLD row for UPDATE and DELETE triggers. Statement-level triggers do not currently have any way to examine the individual row(s) modified by the statement.

Và từ Trigger Procedures:

NEW
Data type RECORD ; variable holding the new database row for INSERT/UPDATE operations in row-level triggers. This variable is NULL in statement-level triggers and for DELETE operations.

Lưu ý những gì nó nói về trigger row-level và trigger tuyên bố cấp.

Bạn có một cò tuyên bố cấp:

... 
FOR EACH STATEMENT 
EXECUTE PROCEDURE f_log_datei(); 

trigger Tuyên bố cấp được kích hoạt một lần cho mỗi câu và một tuyên bố có thể áp dụng cho nhiều hàng nên khái niệm về ảnh hưởng hàng (đó là những gì NEWOLD là về) chỉ đơn giản là không áp dụng.

Nếu bạn muốn sử dụng NEW (hoặc OLD) trong một kích hoạt sau đó bạn muốn kích hoạt để thực hiện cho mỗi hàng bị ảnh hưởng và điều đó có nghĩa là bạn muốn kích hoạt một row-level:

CREATE TRIGGER log_datei AFTER INSERT OR UPDATE OR DELETE 
ON dateien 
FOR EACH ROW 
EXECUTE PROCEDURE f_log_datei(); 

Tôi chỉ thay đổi FOR EACH STATEMENT đến FOR EACH ROW.


kích hoạt của bạn cũng be returning something nên:

A trigger function must return either NULL or a record/row value having exactly the structure of the table the trigger was fired for.
[...]
The return value of a row-level trigger fired AFTER or a statement-level trigger fired BEFORE or AFTER is always ignored; it might as well be null. However, any of these types of triggers might still abort the entire operation by raising an error.

Vì vậy, bạn nên RETURN NEW; hoặc RETURN NULL; trong kích hoạt của bạn. Bạn có một kích hoạt SAU vì vậy nó không quan trọng RETURN bạn sử dụng nhưng tôi muốn đi với RETURN NEW;.

+2

Bạn cũng đã thêm 'RETURN NEW;' vào cuối hàm? – kgrittn

+0

@kgrittn: Đó sẽ là lỗi * tiếp theo *, phải không? Nhưng vâng, tôi thậm chí không thấy điều đó và điều đáng nói đến khi chúng tôi ở đây. –

+1

vâng tôi đã thêm câu lệnh 'RETURN' :) – soupdiver

Các vấn đề liên quan