Postgres触发器不更新指定的列

时间:2016-07-22 14:33:53

标签: sql postgresql

我有以下用户表

  Column   |           Type           |                       Modifiers                       
-----------+--------------------------+-------------------------------------------------------
 id        | integer                  | not null default nextval('accounts_id_seq'::regclass)
 username  | character varying(40)    | 
 email     | character varying(40)    | 
 password  | character varying        | 
 join_date | timestamp with time zone | default now()
 xp        | integer                  | default 0
 level     | integer                  | default 1
 provider  | character varying        | 
 is_admin  | boolean                  | default false

我正在尝试创建一个触发器,它会查看用户xp INTEGER并根据给定的xp更新他的级别

这是我的下面的功能和必要的触发器

CREATE OR REPLACE FUNCTION set_user_level() RETURNS TRIGGER AS $level$

  BEGIN

    CASE 
      WHEN NEW.xp BETWEEN 100 AND 200 THEN
        NEW.level = 2;
      WHEN NEW.xp BETWEEN 200 AND 400 THEN
        NEW.level = 3;
      ELSE
        NEW.level = 1;
    END CASE;

    RETURN NEW;
  END;
$level$ LANGUAGE plpgsql;

CREATE TRIGGER set_user_level AFTER UPDATE ON account FOR EACH ROW EXECUTE PROCEDURE set_user_level();

然而,每当我更新用户xp。用户级别仍然保持为1.我的语法有问题吗?我几乎使用了与文档中指定的语法相同的语法。

1 个答案:

答案 0 :(得分:1)

在您的情况下,您应该使用BEFORE而不是AFTER更新,并且您的代码将完美运行。

请参阅http://sqlfiddle.com/#!15/ef408/1

您可以阅读一些关于触发器here的内容。

有趣的样本:

  

通常,行级BEFORE触发器用于检查或   修改将要插入或更新的数据。例如,a   BEFORE触发器可用于将当前时间插入到   timestamp列,或检查行的两个元素是什么   是一致的。行级AFTER触发器最明智地用于   将更新传播到其他表,或进行一致性检查   对其他桌子。这种分工的原因是:   AFTER触发器可以确定它正在查看行的最终值,   虽然BEFORE触发器不能;可能还有其他BEFORE触发器   在它之后开火。如果您没有特定的理由进行触发   之前或之后,BEFORE案例更有效率,因为   有关操作的信息不必保存到结束   言。