Postgres SQL 函数和触发器在另一个 table 中插入记录
Postgres SQL function and trigger to insert record in another table
我需要帮助来完成以下要求:
- [x]
Profile
table 列 id
, username
, ...
- [x]
Comment
table 列 id
, content
, ...
- [x]
CommentReference
table 列 id
、profile_id
、comment_id
、...
创建新评论时,插入前:
- [ ] 检查
NEW.content
是否引用了用户名,例如 @someusername
- [ ] 检查配置文件中是否存在每个引用 table
- [ ] 对于存在的引用,将配置文件插入
CommentReferences
并评论
现在,我有以下代码:
PS:以下代码有错误,我需要帮助修复它。我正在使用 postgres 版本 12。
CREATE FUNCTION create_comment_usernames_references()
RETURNS trigger AS $$
DECLARE usernames TEXT[];
DECLARE username TEXT;
DECLARE profile_id TEXT; -- profile_id is of type uuid, is it correct to use TEXT here?
BEGIN
-- verify if there are usernames in the comment.content with the username regex
SELECT DISTINCT(
regexp_matches(
NEW.content,
'@(([a-z0-9]*((?<=[a-z0-9])[-|_|\.](?=[a-z0-9]))[a-z0-9]*)*|[a-z0-9]*)',
'g'
)
)[1]
INTO usernames;
FOREACH username IN ARRAY usernames LOOP
SELECT (SELECT id FROM "public"."Profile" WHERE "username" = username) INTO profile_id
INSERT INTO "public"."CommentReference" (comment_id, profile_id) VALUES (NEW.id, profile_id);
END LOOP;
-- return nothing
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER create_comment_usernames_references_trigger
BEFORE INSERT OR UPDATE ON "public"."Comment"
FOR EACH ROW
EXECUTE PROCEDURE create_comment_usernames_references();
自己解决。
最终代码:
CREATE OR REPLACE FUNCTION find_profile_ids_by_usernames_in_text(_value TEXT)
RETURNS TABLE (profile_id uuid) AS
$func$
BEGIN
RETURN QUERY
SELECT
id
FROM
"public"."Profile"
WHERE
username IN (
SELECT DISTINCT(
regexp_matches(
_value,
'@(([a-z0-9]*((?<=[a-z0-9])[-|_|\.](?=[a-z0-9]))[a-z0-9]*)*|[a-z0-9]*)',
'g')
)[1]
);
END
$func$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION create_comment_reference(_comment_id UUID, _content TEXT)
RETURNS integer AS $$
DECLARE
row RECORD;
BEGIN
FOR row IN
SELECT * FROM find_profile_ids_by_usernames_in_text(_content)
LOOP
INSERT INTO
"public"."CommentReference" (comment_id, profile_id)
VALUES
(_comment_id, row.profile_id)
ON CONFLICT DO NOTHING;
END LOOP;
RETURN 1;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION create_comment_reference_trigger_func()
RETURNS trigger AS $$
DECLARE someval integer;
BEGIN
select * from create_comment_reference(NEW.id, NEW.content) into someval;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER create_comment_usernames_references_trigger
AFTER INSERT OR UPDATE ON "public"."Comment"
FOR EACH ROW
EXECUTE PROCEDURE create_comment_reference_trigger_func();
我需要帮助来完成以下要求:
- [x]
Profile
table 列id
,username
, ... - [x]
Comment
table 列id
,content
, ... - [x]
CommentReference
table 列id
、profile_id
、comment_id
、...
创建新评论时,插入前:
- [ ] 检查
NEW.content
是否引用了用户名,例如@someusername
- [ ] 检查配置文件中是否存在每个引用 table
- [ ] 对于存在的引用,将配置文件插入
CommentReferences
并评论
现在,我有以下代码:
PS:以下代码有错误,我需要帮助修复它。我正在使用 postgres 版本 12。
CREATE FUNCTION create_comment_usernames_references()
RETURNS trigger AS $$
DECLARE usernames TEXT[];
DECLARE username TEXT;
DECLARE profile_id TEXT; -- profile_id is of type uuid, is it correct to use TEXT here?
BEGIN
-- verify if there are usernames in the comment.content with the username regex
SELECT DISTINCT(
regexp_matches(
NEW.content,
'@(([a-z0-9]*((?<=[a-z0-9])[-|_|\.](?=[a-z0-9]))[a-z0-9]*)*|[a-z0-9]*)',
'g'
)
)[1]
INTO usernames;
FOREACH username IN ARRAY usernames LOOP
SELECT (SELECT id FROM "public"."Profile" WHERE "username" = username) INTO profile_id
INSERT INTO "public"."CommentReference" (comment_id, profile_id) VALUES (NEW.id, profile_id);
END LOOP;
-- return nothing
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER create_comment_usernames_references_trigger
BEFORE INSERT OR UPDATE ON "public"."Comment"
FOR EACH ROW
EXECUTE PROCEDURE create_comment_usernames_references();
自己解决。
最终代码:
CREATE OR REPLACE FUNCTION find_profile_ids_by_usernames_in_text(_value TEXT)
RETURNS TABLE (profile_id uuid) AS
$func$
BEGIN
RETURN QUERY
SELECT
id
FROM
"public"."Profile"
WHERE
username IN (
SELECT DISTINCT(
regexp_matches(
_value,
'@(([a-z0-9]*((?<=[a-z0-9])[-|_|\.](?=[a-z0-9]))[a-z0-9]*)*|[a-z0-9]*)',
'g')
)[1]
);
END
$func$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION create_comment_reference(_comment_id UUID, _content TEXT)
RETURNS integer AS $$
DECLARE
row RECORD;
BEGIN
FOR row IN
SELECT * FROM find_profile_ids_by_usernames_in_text(_content)
LOOP
INSERT INTO
"public"."CommentReference" (comment_id, profile_id)
VALUES
(_comment_id, row.profile_id)
ON CONFLICT DO NOTHING;
END LOOP;
RETURN 1;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION create_comment_reference_trigger_func()
RETURNS trigger AS $$
DECLARE someval integer;
BEGIN
select * from create_comment_reference(NEW.id, NEW.content) into someval;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER create_comment_usernames_references_trigger
AFTER INSERT OR UPDATE ON "public"."Comment"
FOR EACH ROW
EXECUTE PROCEDURE create_comment_reference_trigger_func();