Postgresql plgpsql-是否可以声明一组记录或表变量?
我有以下-不工作-功能:Postgresql plgpsql-是否可以声明一组记录或表变量?,postgresql,plpgsql,postgresql-8.4,Postgresql,Plpgsql,Postgresql 8.4,我有以下-不工作-功能: CREATE FUNCTION permission_cache_update(affected_user_list int[]) RETURNS TABLE(user_id INT4, permission_id INT4) AS $BODY$ DECLARE current_relations SETOF RECORD; BEGIN WITH affected_user AS ( SELECT unnest(affecte
CREATE FUNCTION permission_cache_update(affected_user_list int[])
RETURNS TABLE(user_id INT4, permission_id INT4)
AS
$BODY$
DECLARE
current_relations SETOF RECORD;
BEGIN
WITH
affected_user AS (
SELECT unnest(affected_user_list) AS u_id
),
affected_relations AS (
SELECT user_role.user_id, role_permission.permission_id
FROM user_role
JOIN role_permission ON user_role.role_id = role_permission.role_id
JOIN affected_user ON affected_user.u_id = user_role.user_id
UNION
SELECT user_permission.user_id, user_permission.permission_id
FROM user_permission
JOIN affected_user ON affected_user.u_id = user_permission.user_id
)
SELECT affected_relations.user_id, affected_relations.permission_id FROM affected_relations
INTO current_relations;
DELETE FROM permission_cache WHERE ARRAY[user_id] <@ affected_user_list;
INSERT INTO permission_cache (user_id, permission_id) SELECT user_id, permission_id FROM current_relations;
END
$BODY$
LANGUAGE plpgsql;
我认为这是可能的表->二维数组转换,但这是复杂的,所以如果它可能与记录,这将是更好的
解决方案:
使用1d数组创建循环比使用记录或2d数组更容易:
CREATE FUNCTION permission_cache_update(
IN affected_user_list INT4 []
)
RETURNS VOID
AS
$BODY$
DECLARE
user_index INT4;
current_user_id INT4;
current_permission_relations INT4 [];
deleted_permission_relations INT4 [];
inserted_permission_relations INT4 [];
BEGIN
FOR user_index IN 1 .. array_upper(affected_user_list, 1) LOOP
current_user_id := affected_user_list[user_index];
WITH
user_permission_summary AS
(
SELECT
role_permission.permission_id
FROM user_role, role_permission
WHERE role_permission.role_id = user_role.role_id AND user_role.user_id = current_user_id
UNION
SELECT
user_permission.permission_id
FROM user_permission
WHERE user_permission.user_id = current_user_id
)
SELECT
array_agg(permission_id)
FROM user_permission_summary
INTO current_permission_relations;
SELECT
array_agg(permission_cache.permission_id)
FROM permission_cache
WHERE permission_cache.user_id = current_user_id AND ( current_permission_relations IS NULL OR
NOT (ARRAY [permission_cache.permission_id] <@ current_permission_relations) )
INTO deleted_permission_relations;
SELECT
array_agg(inserted_permission_id)
FROM unnest(current_permission_relations) AS inserted_permission_id
WHERE NOT EXISTS(SELECT
1
FROM permission_cache
WHERE permission_cache.user_id = current_user_id AND
permission_cache.permission_id = inserted_permission_id)
INTO inserted_permission_relations;
DELETE FROM permission_cache
WHERE permission_cache.user_id = current_user_id AND
permission_cache.permission_id = ANY (deleted_permission_relations);
INSERT INTO permission_cache (user_id, permission_id)
SELECT
current_user_id,
inserted_permission_id
FROM unnest(inserted_permission_relations) AS inserted_permission_id;
END LOOP;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
关:
Pplpgsql是一种非常糟糕的语言,文档甚至很糟糕,我不喜欢它。。。
很抱歉,代码格式化,我的IDE中的自动格式化不太好…:S我认为这个简化的SQL函数可以满足您的需要:
CREATE FUNCTION permission_cache_update(affected_user_list int[])
RETURNS void AS
$func$
DELETE FROM permission_cache p
USING (SELECT unnest($1) AS u_id) a
WHERE p.user_id = a.u_id;
INSERT INTO permission_cache (user_id, permission_id)
SELECT u.user_id, r.permission_id
FROM user_role u
JOIN role_permission r USING (role_id)
JOIN (SELECT unnest($1) AS u_id) a ON a.u_id = u.user_id
UNION
SELECT p.user_id, p.permission_id
FROM user_permission p
JOIN (SELECT unnest($1) AS u_id) a ON a.u_id = p.user_id;
$func$ LANGUAGE sql;
将极大地简化这一过程,但仅在Postgres 9.1中引入。再一次,你过时的版本挡道了
仅在Postgres 9.2中为plpgsql的早期SQL函数引入了按名称引用参数。所以我使用位置参数$1。您仍然声明:返回TABLEuser\u id INT4,permission\u id INT4。这是一个工件还是你真的想额外返回行?哦,不:D这只是以前代码的一部分…是的,但我不想简化,在这个函数的下一个版本中,我将删除并插入真正需要的内容。。。我想了想,二维数组可以吗?我认为有记录和没有循环是不可能的。。。记录集不工作,我不认为有记录数组这样的东西……@inf3rno:当然有这样的东西。您可以使用多维数组或记录数组,即使在良好的旧Postgres 8.4中也是如此。我回答了一个问题。8.4的工作原理与此相同。顺便说一句,临时桌子怎么了?对于更大的场景,这通常更快。在现代的博士后考试中,你可能只需要一个数据修改CTE就可以完成这一切。
CREATE FUNCTION permission_cache_update(affected_user_list int[])
RETURNS void AS
$func$
DELETE FROM permission_cache p
USING (SELECT unnest($1) AS u_id) a
WHERE p.user_id = a.u_id;
INSERT INTO permission_cache (user_id, permission_id)
SELECT u.user_id, r.permission_id
FROM user_role u
JOIN role_permission r USING (role_id)
JOIN (SELECT unnest($1) AS u_id) a ON a.u_id = u.user_id
UNION
SELECT p.user_id, p.permission_id
FROM user_permission p
JOIN (SELECT unnest($1) AS u_id) a ON a.u_id = p.user_id;
$func$ LANGUAGE sql;