【发布时间】:2014-03-27 19:39:29
【问题描述】:
我正在尝试在 Postgres 中创建一个触发器/函数,该触发器/函数将在插入表时检查是否已经有其他成员发布的具有相同内容的另一个帖子。 如果有帖子,这个函数不会插入新的,保持表格不变。否则,将被添加。
到目前为止,触发器和函数如下所示:
触发器:
CREATE TRIGGER isPostUnique
AFTER INSERT ON posts
FOR EACH ROW
EXECUTE PROCEDURE deletePost();
功能:
CREATE FUNCTION deletePost() RETURNS TRIGGER AS $isPostUnique$
BEGIN
IF (EXISTS (SELECT * FROM posts p1, posts p2
WHERE (p1.userID <> p2.userID)
AND (p1.content LIKE p2.content)))
THEN
DELETE FROM NEW WHERE (posts.postID = NEW.postID);
RETURN NEW;
END IF;
END;
$isPostUnique$ LANGUAGE plpgsql;
添加函数和触发器没有任何错误,但是当我尝试运行以下查询来测试它时:INSERT INTO posts VALUES (7, 3, 'test redundant post', 10, 1); 我收到此错误
ERROR: relation "new" does not exist
LINE 1: DELETE FROM NEW WHERE (posts.postID = NEW.postID)
^
QUERY: DELETE FROM NEW WHERE (posts.postID = NEW.postID)
CONTEXT: PL/pgSQL function dp() line 7 at SQL statement
我知道您不能在 FOR EACH ROW 插入中使用“NEW”,但我不知道如何实现这一点。
【问题讨论】:
-
new只能在行级 (for each row) 触发器中使用。您究竟希望delete from new做什么?new是单行(又名“记录”),不是可以从中删除的表。 -
我真的是 Postgres 的新手,我只是从文档中尽可能多地尝试,所以我确信其中的很多内容都是没有意义的。我想要完成的是找到与另一个具有相同内容的新插入,并删除刚刚插入的那个。
-
为了防止插入,只需从触发器返回
NULL。 Quote from the manual: "BEFORE 触发的行级触发器可以返回 null 以指示触发器管理器跳过该行的其余操作(即,不会触发后续触发器,并且不会触发 INSERT/UPDATE/DELETE发生在这一行" -
好的,我将触发器中的
AFTER INSERT ON替换为BEFORE INSERT...并取出THEN DELETE FROM...RETURN NEW并将THEN中的内容替换为RETURN NULL。但是,现在我无法在表格中添加任何内容。 -
有没有我可以编写类似于
IF ((NEW.content LIKE posts.content) AND (NEW.userID <> posts.userID))的IF 语句而不会出现missing FROM错误?
标签: sql function postgresql triggers plpgsql