带参数的Postgresql触发函数

问题描述 投票:0回答:4

我想在 postgresql 中名为 takes 的表上创建一个触发器,以更新另一个名为 student 的表中的值 我正在尝试按以下方式进行操作。但我收到一个错误,指出“OLD”附近存在语法错误。我不明白这有什么问题。这是我的代码:

CREATE OR REPLACE FUNCTION upd8_cred_func
      (id1 VARCHAR, gr1 VARCHAR,id2 VARCHAR, gr2 VARCHAR) 
      RETURNS void AS $$
 BEGIN
    IF  (id1=id2 and gr1 is null and gr2 is not null) THEN 
        update student set tot_cred = tot_cred + 6 where id = id1;
    END IF;
    RETURN;
 END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER upd8_cred
    AFTER UPDATE ON takes
    FOR EACH ROW
    EXECUTE PROCEDURE upd8_cred_func(OLD.id,OLD.grade,NEW.id,NEW.grade);
sql postgresql triggers
4个回答
49
投票

您不需要将 NEW 和 OLD 作为参数传递给触发函数。它们自动可用:

http://www.postgresql.org/docs/9.1/interactive/trigger-definition.html

触发器函数必须声明为不带参数且返回类型触发器的函数。 (触发器函数通过专门传递的 TriggerData 结构接收输入,而不是以普通函数参数的形式。)

关于传递给触发器过程的记录,请参见http://www.postgresql.org/docs/9.1/interactive/plpgsql-trigger.html :

当 PL/pgSQL 函数作为触发器调用时,会在顶级块中自动创建几个特殊变量。它们是:[...]新、[...]旧[...]

正如下面评论中的SeldomNeedy指出的那样,您仍然可以向触发函数传递和使用参数。您声明该函数不带参数,但是当定义触发器时(通过

CREATE TRIGGER
),您可以添加一些参数。

它们将可用于触发器,如

TG_NARG
(此类参数的数量)和
TG_ARGV[]
text 值的数组)。


30
投票

正如 Greg 所说,触发器函数可以接受参数,但函数本身不能有声明的参数。这是 plpgsql 中的一个简单示例:

CREATE TABLE my_table ( ID SERIAL PRIMARY KEY ); -- onelined for compactness

CREATE OR REPLACE FUNCTION raise_a_notice() RETURNS TRIGGER AS
$$
DECLARE
    arg TEXT;
BEGIN
    FOREACH arg IN ARRAY TG_ARGV LOOP
        RAISE NOTICE 'Why would you pass in ''%''?',arg;
    END LOOP;
    RETURN NEW; -- in plpgsql you must return OLD, NEW, or another record of table's type
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER no_inserts_without_notices BEFORE INSERT ON my_table
FOR EACH ROW EXECUTE PROCEDURE raise_a_notice('spoiled fish','stunned parrots');

INSERT INTO my_table DEFAULT VALUES;

-- the above kicks out the following:
--
-- NOTICE:  Why would you pass in 'spoiled fish'?
-- NOTICE:  Why would you pass in 'stunned parrots'?
--

还有一些其他的好处,例如

TG_NARGS
(无需循环即可知道有多少个参数)在 文档中讨论。那里还提供了有关如何获取触发表名称的信息,以防您对跨多个表的一个触发器函数拥有大部分但不完全共享的逻辑。


19
投票

触发函数可以有参数,但是,您不能像普通函数一样传递这些参数(例如函数定义中的参数)。你可以获得相同的结果......在 python 中,你可以访问旧数据和新数据,如上面答案所述。例如,我可以在Python中使用TD['new']['column_name']来引用column_name的新数据。您还可以访问特殊变量 TD['args']。所以,如果你喜欢:

create function te() returns trigger language plpython2u as $function$
    plpy.log("argument passed 1:%s 2:%s" %(TD['args'][0], TD['args'][1], ))
$function$

create constraint trigger ta after update of ttable
for each for execute procedure te('myarg1','myarg2');

当然,这些参数是静态的,但是,当从多个触发器声明调用公共触发器函数时,它们很有用。我非常确定相同的变量可用于其他存储过程语言。 (很抱歉,如果代码不能逐字工作,但是,我确实练习了这种技术,所以我知道你可以传递参数!)。


0
投票

触发函数不能有参数(声明的参数),如下所示:

CREATE FUNCTION my_func(num INTEGER) RETURNS trigger
AS $$                 -- ↑ Here ↑
BEGIN
END;
$$ LANGUAGE plpgsql;

否则会出现以下错误:

错误:触发器函数不能有声明的参数

我实验了一个触发功能,并做了如下的备忘录:

  • 触发功能:

    • 必须没有参数,否则会出错。

    • 必须用触发器调用,否则会出错。

    • 不能用

      LANGUAGE SQL
      创建,否则会出现错误

    • 必须在

      trigger
      子句中包含
      RETURNS <type>
      才能与触发器一起使用,否则会出错。

  • 触发程序不存在。

© www.soinside.com 2019 - 2024. All rights reserved.