我试图在Postgres中创建一个Trigger / Function,它会在插入表时检查具有相同内容的其他成员是否已经有另一个帖子。 如果有帖子,此功能将不会插入新的并保持表格不变。否则,它将被添加。
到目前为止,触发器和函数看起来像:
触发:
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
我知道你不能使用&#39; NEW&#39;在FOR EACH ROW
插入,但我不知道如何实现这一点。
答案 0 :(得分:2)
当然,您可以在NEW
触发器功能中使用FOR EACH ROW
。你无法指导DELETE
语句。它是行类型(data type HeapTuple
to be precise),而不是表格。
如果已经存在相同的内容,中止 INSERT
静默(无异常)...
CREATE FUNCTION deletePost()
RETURNS TRIGGER AS
$func$
BEGIN
IF EXISTS (
SELECT 1
FROM posts p
WHERE p.content = NEW.content
-- AND p.userID <> NEW.userID -- I doubt you need this, too?
) THEN
RETURN NULL; -- cancel INSERT
ELSE
RETURN NEW; -- go ahead
END IF;
END
$func$ LANGUAGE plpgsql;
当然这只适用于触发......
...
BEFORE INSERT ON posts
...
UNIQUE
constraint或唯一索引(几乎相同的效果)可能是一个更好的解决方案:
CREATE UNIQUE INDEX posts_content_uni_idx (content);
在尝试插入重复值时会引发异常。无需触发。
它还提供了非常需要的索引来加快速度。