Postgresql

觸發功能不存在,但我很確定它存在

  • October 23, 2021

我有一個程序:

create or replace procedure pro_update_last_read(in input_sensor_id integer, in read_time timestamp)
as
$$
begin
   update sensor
   set last_read = read_time
   where sensor_id = input_sensor_id;
end;
$$ language plpgsql;

以及一個呼叫它的觸發器:

create trigger tri_last_read
   after insert or update of report_time
   on report
execute procedure pro_update_last_read(sensor_id, report_time);

但是,在創建觸發器時,我收到錯誤消息:

 [42883] ERROR: function pro_update_last_read() does not exist

為什麼會發生此錯誤?

您必須使用函式,而不是過程:

CREATE FUNCTION pro_update_last_read() RETURNS trigger ...

必須定義觸發器FOR EACH ROW,並且不能將列傳遞給觸發器函式。

您訪問觸發器函式中的列的方式是通過NEW變數:NEW.sensor_idNEW.report_time.

我將 Postgres函式的廣泛誤稱“儲存過程”歸咎於。這導致了使用這種語法創建觸發器的愚蠢行為:

CREATE TRIGGER ... FOR ... EXECUTE **PROCEDURE** function_name ...

不確定 SQL 標準的責任有多大,將“SQL 過程語句”稱為觸發操作。

在 Postgres 10 之前,潛在的混亂是有限的,因為只有functions。但是 Postgres 11 終於引入了真正的SQL過程。難怪有些人被誤導在那裡提供程序

Postgres 11 中添加了更明智的替代語法:

CREATE TRIGGER ... FOR ... EXECUTE **FUNCTION** function_name ...

這不是向後兼容的。所以需要一些時間來接管。

如果您不必與 Postgres 10 或更早版本保持兼容,請使用新語法來提醒自己使用函式- 就像 Laurenz 指示的那樣。

有關的:

(最終實現儲存過程以及觸發器的新語法的也是 Peter Eisentraut。)

引用自:https://dba.stackexchange.com/questions/251189