在PostgreSQL中触发

时间:2011-02-01 15:19:10

标签: postgresql triggers

我的表格"Candidates"包含id(主键)和application_counter
和表"Applications"使用外键(candidate_id)。我希望每次添加或删除应用程序时修改application_counter(或通过更改candidate_id进行修改)。

我所能做的就是写:

CREATE TRIGGER myTrigger AFTER INSERT OR DELETE OR UPDATE
ON "Applications" FOR EACH ROW
EXECUTE PROCEDURE funcname ( arguments )

问题是如何编写此触发器?

http://www.postgresql.org/docs/8.1/interactive/sql-createtrigger.html

中的概要
CREATE TRIGGER name { BEFORE | AFTER } { event [ OR ... ] }
ON table [ FOR [ EACH ] { ROW | STATEMENT } ]
EXECUTE PROCEDURE funcname ( arguments )

2 个答案:

答案 0 :(得分:3)

CREATE TRIGGER myname AFTER INSERT, DELETE OR UPDATE 
ON table applications
EXECUTE PROCEDURE myfunc();

CREATE FUNCTION myfunc() RETURNS TRIGGER AS 
BEGIN
    IF TG_OP != 'DELETE' THEN
        update candicate set application_count = application_count + 1 where id = new.candidate_id;
    END IF;
    IF TG_OP != 'INSERT' THEN
        update candicate set application_count = application_count + 1 where id = old.candidate_id;
    END IF;
END;

我希望你能得到这个想法......现在也可以使用更新的candidate_id。

答案 1 :(得分:3)

我将使用两个表的视图INNER JOIN,并计算applications表中的行数。 (参见COUNT()。)可以禁用触发器;该视图将始终为您提供正确的答案。

(稍后......)

我知道您希望将“应用程序”表中候选人的行限制为3或更少。在这种情况下,我认为最好对“应用程序”使用CHECK()约束,而不是对“应用程序”的触发器和对“候选者”的CHECK()约束的组合。

要在PostgreSQL中执行此操作,您必须使用一个函数,并从CHECK()调用该函数。 (据我所知。你仍然无法在SELECT约束中执行任意CHECK()语句,对吧?)所以,你要创建这个函数,

CREATE FUNCTION num_applications(cand_id integer)
  RETURNS integer AS
$BODY$ 

  DECLARE 
    n integer; 
  BEGIN 
    select count(*) 
    into n 
    from applications
    where (candidate_id = cand_id);

    return n; 
  END; 
$BODY$ 
LANGUAGE plpgsql;

然后你要在表'应用程序'中添加一个CHECK()约束。

ALTER TABLE applications
  ADD CONSTRAINT max_of_three CHECK (num_applications(candidate_id) < 3);

“&lt; 3”,因为在添加行之前评估CHECK()约束。可能值得测试看看它如何与延迟约束一起运行。如果我以后有时间,我会这样做。