加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

postgresql – plgpsql – 是否可以声明setof记录或表变量?

发布时间:2020-12-13 15:52:25 所属栏目:百科 来源:网络整理
导读:我有以下 – 不工作 – 功能: 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(affe
我有以下 – 不工作 – 功能:

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;

我想将current_relations中的当前用户权限关系存储为(INT4,INT4).是否可以使用没有循环和临时表的变量来执行此操作?

我稍后会使用这样的东西,所以我真的需要它作为变量,而不是子查询

DELETE FROM permission_cache WHERE ARRAY[user_id] <@ affected_user_list AND NOT IN (SELECT user_id,permission_id FROM current_relations);

INSERT INTO permission_cache (user_id,permission_id FROM current_relations WHERE NOT EXIST (SELECT user_id,permission_id FROM permission_cache);

我认为有可能用表 – > 2d阵列转换,但这很复杂,所以如果有可能记录,那会更好……

解:

使用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中的autoformat不太好……: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;

Writable CTE (a.k.a. data-modifying CTE)将极大地简化这一过程,但仅在Postgres 9.1中引入.再一次,你过时的版本就是这样.

按名称引用参数仅在Postgres 9.2 for SQL函数中引入(之前的plpgsql).所以我使用位置参数$1.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读