首页 > 解决方案 > 如何编写将最后插入的行放入表中的触发器?

问题描述

is_continued_post如果某些条件是关于先前插入表中的行的某些条件为真,我将填充一个字段(它是同一个用户,并且它inserted_at距离新行 insert_at 不到 N 分钟)。

将新评论插入数据库时​​。我想获取插入的最后一条评论(具有相同的post_id),然后检查旧行 user_id 是否与新行 user_id 相同,并且旧行在新行之前不到 2 分钟插入。如果这是真的,我想在插入之前将新行上的布尔值翻转为真。

Postgresql 触发器可以做到这一点吗?还是有更好的方法来做到这一点?

到目前为止,这是我想出的:

CREATE OR REPLACE FUNCTION update_message_cont()
RETURNS trigger AS $$
BEGIN
  old := (SELECT m0.user_id, m0.inserted_at FROM messages AS m0 WHERE (m0.post_id = NEW.post_id) ORDER BY m0.inserted_at DESC LIMIT 1);
  NEW.is_continued := CASE
      WHEN old is NULL THEN FALSE
      WHEN old.user_id = NEW.user_id AND ((NEW.inserted_at - old.inserted_at) < 120) THEN TRUE
  END;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

标签: postgresql

解决方案


是的,这是可能的,但前提是您的表中有一个列可以让您识别最后插入的行。插入顺序并未反映在表中。

所以介绍一个专栏

inserted_at timestamp with time zone DEFAULT clock_timestamp() NOT NULL

上的索引(post_id, inserted_at)将使查询快速。

整个触发器可能如下所示:

CREATE FUNCTION update_message_cont() RETURNS trigger AS
$$BEGIN
   SELECT user_id IS NOT DISTINCT FROM NEW.user_id INTO NEW.is_continued
   FROM messages
   WHERE post_id = NEW.post_id
     AND inserted_at > NEW.inserted_at - INTERVAL '120 seconds'
   ORDER BY inserted_at DESC
   LIMIT 1;

   -- if no previous row was found:
   IF NEW.is_continued IS NULL THEN
      NEW.is_continued = FALSE;
   END IF;

   RETURN NEW;
END;$$ LANGUAGE plpgsql;

CREATE TRIGGER update_message_cont BEFORE INSERT ON messages
   FOR EACH ROW EXECUTE PROCEDURE update_message_cont();

推荐阅读