31

私は非常に単純なトリガーを持っています:

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

なぜこのエラーが発生したのですか?ドキュメントを調べたところ、私と同じように新しいものが使用されているようです。

4

1 に答える 1

49

細かいマニュアルから:

36.1。トリガー動作の概要
[...]
行レベルのトリガーの場合、入力データには、とトリガーの行、および/またはとトリガーのNEW行も含まれます。ステートメントレベルのトリガーには、現在、ステートメントによって変更された個々の行を調べる方法がありません。INSERTUPDATEOLDUPDATEDELETE

そしてトリガー手順から:

NEW
データ型RECORD; 行レベルのトリガーでINSERT/操作の新しいデータベース行を保持する変数。UPDATEこの変数はNULL、ステートメントレベルのトリガーおよびDELETE操作用です。

行レベルのトリガーとステートメントレベルのトリガーについての説明に注意してください。

ステートメントレベルのトリガーがあります。

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

ステートメントレベルのトリガーはステートメントごとに1回トリガーされ、ステートメントは複数の行に適用できるため、影響を受ける行の概念(これが何であるか)は単純NEWOLD適用されません。

NEWトリガーで(または)を使用する場合はOLD、影響を受ける行ごとにトリガーを実行する必要があります。つまり、行レベルのトリガーが必要です。

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

に変更FOR EACH STATEMENTしましたFOR EACH ROW


トリガーも何かを返す必要があります:

トリガー関数はNULL、トリガーが起動されたテーブルの構造を正確に持つレコード/行の値を返す必要があります。
[...]起動された行レベルのトリガーまたは起動されたステートメント
レベルのトリガーの戻り値、または常に無視されます。nullの場合もあります。ただし、これらのタイプのトリガーはいずれも、エラーを発生させて操作全体を中止する可能性があります。AFTERBEFOREAFTER

だからあなたはすべきRETURN NEW;RETURN NULL;、あなたの引き金になります。AFTERトリガーがあるので、どのRETURNを使用してもかまいませんが、私は。を使用しRETURN NEW;ます。

于 2012-06-12T17:31:51.843 に答える