【问题标题】:Postgres trigger to update counter in another table not workingPostgres触发器更新另一个表中的计数器不起作用
【发布时间】:2023-03-05 14:44:01
【问题描述】:
  • users 表和places 表。

  • users 表有列id(主键)、usernameplace_count

  • places 表有列 id(主键)、nameuser_id(用户 ID 外键)

  • 每个用户都可以发布多张照片,所以我想要 列“place_count”以保留用户特定位置的计数 地点表(例如,具有 id 1 的用户具有 place_count = 150,具有 id 2 具有 place_count = 244 等)。

我使用了触发器

触发功能

CREATE FUNCTION log_place_count_update_to_user()
RETURNS TRIGGER as $$
BEGIN
    IF (TG_OP = `INSERT`) THEN
        UPDATE users 
        SET place_count = place_count + 1
        WHERE user_id;
    ELSEIF (TG_OP = `DELETE`) THEN
        UPDATE users
        SET place_count = place_count - 1 
        WHERE id = NEW.user_id AND place_count > 0;
    END IF;
    RETURN NEW;
END
$$
LANGUAGE PLPGSQL;

触发器创建

CREATE TRIGGER log_place_count_update
    AFTER INSERT OR DELETE
    ON places
    FOR EACH ROW
    EXECUTE PROCEDURE log_place_count_update_to_user();

我在users 表中插入了一些用户,初始值为place_count = 0。

问题:当我使用名称和 user_id 更新地点时,我希望触发器将 users 表中的 place_count 增加 1。但是place_countuser 表中没有发生任何增量。
我做错了什么?

【问题讨论】:

  • 不要实现计数。删除users 中的列place_count 和触发器。冗余数据可能导致不一致。您始终可以查询 right 值。为方便起见,您可以创建一个视图,列出用户和计数。
  • 我现在不知道视图。刚从 postgres 开始。但是感谢您提出来,我当然会查看视图并查看它可以解决我想要的功能的地方。在我的方法的背景下,为什么会出错?

标签: sql postgresql triggers


【解决方案1】:

回答您的问题:多个语法错误。这应该有效:

CREATE FUNCTION log_place_count_update_to_user()
  RETURNS TRIGGER
  LANGUAGE plpgsql AS
$func$
BEGIN
   CASE TG_OP
   WHEN 'INSERT' THEN            -- single quotes
      UPDATE users AS u
      SET    place_count = u.place_count + 1
      WHERE  u.id = NEW.user_id;  -- fixed
   WHEN 'DELETE' THEN
      UPDATE users AS u
      SET    place_count = u.place_count - 1 
      WHERE  u.id = OLD.user_id
      AND    u.place_count > 0;
   ELSE
      RAISE EXCEPTION 'Unexpected TG_OP: "%". Should not occur!', TG_OP;
   END CASE;
   
   RETURN NULL;      -- for AFTER trigger this can be NULL
END
$func$;

您的原件实际上会产生错误消息。

并且您的触发器需要寻址 INSERT 而不是 UPDATE

CREATE TRIGGER log_place_count_update
AFTER INSERT OR DELETE ON places
FOR EACH ROW EXECUTE PROCEDURE log_place_count_update_to_user();

UPDATE 尚未被覆盖!)

但是(如已评论)我不会去那里。使用触发器记数既昂贵又容易出错。

places (user_id) 上有一个索引(就像你应该有的那样)这个查询非常快地返回当前计数:

SELECT count(*) FROM places WHERE user_id = $user_id;

【讨论】:

  • 感谢指正。我复制粘贴的整个代码 sn-p 用 CREATE OR REPLACE FUNCTION 替换 CREATE FUNCTION,因为我必须替换我以前的函数。之后,我在 users 表中插入了另一组与用户 id 相关的 user_id 的地方。插入这些后,我仍然没有更新 users 表中的 place_count 字段
  • @Jake:哦,触发器也有错误。我假设users.place_count 定义为NOT NULL?
  • 是的 users.place_count 定义为 NOT NULL。但是在更新任何地方之前。我插入了一些用户并将place_count的初始值设置为0
  • 嘿,对不起,这乱七八糟的。您的解决方案确实解决了它。错误地你的And your trigger needs to address INSERT instead of UPDATE 被跳过了。这是因为我在 UPDATE 插入 INSERT。它现在工作正常。浪费了8小时哈哈。真的很感谢你
  • 嘿,你的删除条件不起作用。增量计数正在插入。但递减计数不适用于删除地点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-13
  • 2011-03-23
  • 2011-07-12
相关资源
最近更新 更多