Postgres 触发器不更新指定的列

Kan*_*naj 2 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
Run Code Online (Sandbox Code Playgroud)

我正在尝试创建一个触发器,它查看用户 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();
Run Code Online (Sandbox Code Playgroud)

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

Rap*_*aus 5

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

http://sqlfiddle.com/#!15/ef408/1

您可以在此处阅读一些有关触发器的信息

有趣的样本:

通常,行级 BEFORE 触发器用于检查或修改将被插入或更新的数据。例如,BEFORE 触发器可用于将当前时间插入时间戳列,或检查行的两个元素是否一致。行级 AFTER 触发器最明智地用于将更新传播到其他表,或对其他表进行一致性检查。这种分工的原因是 AFTER 触发器可以确定它看到的是行的最终值,而 BEFORE 触发器不能;在它之后可能还有其他 BEFORE 触发器触发。如果您没有特定的理由在 BEFORE 或 AFTER 之前创建触发器,则 BEFORE 情况更有效,因为有关操作的信息不必保存到语句结束。