创建触发器以使用子查询自动更新列

Create trigger to automatically update column with subquery

在我的应用程序中,我有几个表,lessonsvotes。它们的外观如下:

课程

+-------------+---------+----------------------+
| Column      | Type    | Modifiers            |
|-------------+---------+----------------------|
| id          | uuid    |  not null            |
| votes_total | integer |  not null default 0  |
+-------------+---------+----------------------+

投票

+-------------+---------+-------------+
| Column      | Type    | Modifiers   |
|-------------+---------+-------------|
| positive    | boolean |  not null   |
| user_id     | uuid    |  not null   |
| lesson_id   | uuid    |  not null   |
+-------------+---------+-------------+

每当插入、更新或删除 votes 中的一行时,我想使用子查询更新相关课程的 votes_total 列。这是我尝试过的:

CREATE PROCEDURE update_lesson_votes_total()
LANGUAGE SQL
AS $$
UPDATE lessons
SET votes_total = (
  SELECT SUM(CASE WHEN positive THEN 1 ELSE -1 END)
  FROM votes
  WHERE lesson_id = NEW.lesson_id
)
WHERE id = NEW.lesson_id;
$$;

CREATE TRIGGER votes_change
AFTER INSERT OR UPDATE OR DELETE ON votes
FOR EACH ROW
EXECUTE PROCEDURE update_lesson_votes_total();

但是,当我在迁移中尝试 运行 时,出现以下错误:

(Postgrex.Error) ERROR 42601 (syntax_error) cannot insert multiple commands into a prepared statement

您好,您的函数必须 return 一个触发器。您不能在删除触发器中使用 new。您必须创建至少 2 个调用相同函数的触发器,并使用 TG_OP 了解该函数是由插入、更新或删除触发的。

然后在 case 或 if 语句中,您可以使用 new 或 old 来获取 id 的值。

CREATE FUNCTION update_lesson_votes_total()
returns trigger
LANGUAGE plpgsql
AS $$
begin
UPDATE lessons
SET votes_total = (
  SELECT SUM(CASE WHEN positive THEN 1 ELSE -1 END)
  FROM votes
  WHERE lesson_id = NEW.lesson_id
)
WHERE id = NEW.lesson_id;

return null;
end;
$$;

CREATE TRIGGER votes_change_u_i
AFTER INSERT OR UPDATE ON votes
FOR EACH ROW
EXECUTE PROCEDURE update_lesson_votes_total();

CREATE TRIGGER votes_change_d
AFTER DELETE ON votes
FOR EACH ROW
EXECUTE PROCEDURE update_lesson_votes_total();