带参数的Postgresql触发函数

27 sql postgresql triggers

我想创建一个触发器上称为表需要在PostgreSQL中更新另一个表称为价值的学生 ,我试图做到这一点通过以下方式.但我收到一个错误,"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);
Run Code Online (Sandbox Code Playgroud)

Ars*_*en7 31

您无需将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函数被调用为触发器时,会在顶级块中自动创建几个特殊变量.它们是:[...] NEW,[...] OLD [...]

正如SeldomNeedy在下面的评论中指出的那样,您仍然可以将参数传递给触发器功能.您将该函数声明为不带参数,但在定义触发器(by CREATE TRIGGER)时,您可以添加一些参数.

它们将作为触发器TG_NARG(此类参数的数量)和TG_ARGV[](文本值数组)可用.

  • 关于plpgsql触发器函数无法接受*参数*,这个答案(可以说也是这个规范)是错误的**.它们必须简单地定义为"不带参数".可以使用`TG_ARGV`数组(索引从0开始)访问传递给触发器函数的参数.这在[触发程序](http://www.postgresql.org/docs/9.1/static/plpgsql-trigger.html)文档中指定. (12认同)

Sel*_*edy 17

正如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'?
--
Run Code Online (Sandbox Code Playgroud)

TG_NARGS文档中讨论了一些其他的好东西,例如(知道你有多少args,而没有循环遍历它们).还有关于如何获取触发表的名称的信息,以防你有一个跨越多个表的触发器函数的大部分但非完全共享的逻辑.


Gre*_*reg 14

触发器函数可以有参数,但是,您不能像普通函数那样传递这些参数(例如函数定义中的参数).您可以获得相同的结果...在python中,您可以访问OLD和NEW数据,如上面的答案所述.例如,我可以在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');
Run Code Online (Sandbox Code Playgroud)

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