带参数的PostgreSQL触发器函数

ghg1uchk  于 12个月前  发布在  PostgreSQL
关注(0)|答案(4)|浏览(177)

我想在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);

字符串

3xiyfsfu

3xiyfsfu1#

你不需要将NEW和OLD作为参数传递给trigger函数。它们在那里 * 自动 * 可用:
http://www.postgresql.org/docs/9.1/interactive/trigger-definition.html
trigger函数必须声明为不带参数并返回类型trigger的函数。(trigger函数通过特殊传递的TriggerData结构接收其输入,而不是以普通函数参数的形式。)
关于传递给触发器过程的记录,请参见http://www.postgresql.org/docs/9.1/interactive/plpgsql-trigger.html
当一个PL/pgSQL函数作为触发器被调用时,在顶层块中会自动创建几个特殊的变量。它们是:[...] NEW,[...] OLD [...]
正如SeldomNeedy在下面的注解中指出的那样,你仍然可以向触发器函数传递和使用参数。你 * 声明 * 函数不带参数,但是当 * 定义 * 触发器(通过CREATE TRIGGER)时,你可以添加一些参数。
它们将作为TG_NARG(此类参数的数量)和TG_ARGV[]text 值的数组)可用于触发器。

eagi6jfj

eagi6jfj2#

正如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'?
--

字符串
the docs中还讨论了一些其他的好东西,比如TG_NARGS(不用循环就能知道你得到了多少个参数)。还有关于如何获取触发表的名称的信息,以防你有一个跨越多个表的查询函数的大部分但不完全共享的逻辑。

rdlzhqv9

rdlzhqv93#

trigger函数可以有参数,但是不能像普通函数那样传递这些参数(例如,函数定义中的参数)。你可以得到相同的结果......在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');

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

zwghvu4y

zwghvu4y4#

trigger function不能有如下所示的参数(声明的参数):

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

字符串
否则会出现以下错误:
错误:触发器函数不能有声明的参数
而且,事件触发器函数不能有如下所示的参数(声明的参数):

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


否则会出现以下错误:
错误:事件触发器函数不能有声明的参数
我尝试了触发器和事件触发器函数,并制作了如下所示的备忘录:

  • 触发器和事件触发器的功能:
  • 必须没有参数,否则有错误。
  • 必须分别用触发器和事件触发器调用,否则会出错。
  • 不能用LANGUAGE SQL创建,否则会出现错误。
  • 必须在RETURNS <type>子句中分别具有triggerevent_trigger,以分别与trigger和event_trigger一起使用,否则会出现错误。
  • 触发器和事件触发器程序不存在。

相关问题