You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL查询用户数据库权限的脚本逻辑问题排查

问题排查与修正

你的脚本存在三个核心问题,导致输出结果与实际不符:

1. 权限判断逻辑错误

has_database_privilege函数传入多个权限(如'connect, create, temp')时,作用是检查用户是否同时拥有所有指定权限,而非拥有其中任意一项。你的case语句按组合权限顺序判断,不仅无法准确收集用户实际拥有的权限,还可能因public角色的默认权限(connect、temp)导致误判。

2. 循环变量引用错误

循环内的RAISE NOTICE语句使用了db.datname,但原查询中的db表别名在循环块中已失效,必须改用循环变量db_r.datname,否则会触发语法错误。

3. 未区分直接权限与继承权限(可选)

默认情况下,has_database_privilege会包含用户从public等角色继承的权限。如果只想查看用户直接拥有的权限,需添加NO INHERIT选项。


修正后的脚本

以下脚本通过逐个检查单权限并拼接结果,能准确输出用户实际拥有的数据库权限:

DO
$$
DECLARE
    db_r record;
BEGIN
    FOR db_r IN
        SELECT 
            db.datname,
            rl.rolname,
            STRING_AGG(priv, ', ') AS privileges
        FROM pg_roles rl
        CROSS JOIN pg_database db
        -- 逐个检查需要验证的权限
        CROSS JOIN UNNEST(ARRAY['connect', 'create', 'temp']) AS priv
        WHERE 
            rl.rolcanlogin
            AND db.datallowconn
            AND db.datname NOT IN ('postgres', 'template0', 'template1')
            -- 检查当前用户是否拥有该权限
            AND has_database_privilege(rl.rolname, db.datname, priv)
            -- 如果只想看直接权限,替换上面的条件为:
            -- AND has_database_privilege(rl.rolname, db.datname, priv, 'NO INHERIT')
        GROUP BY db.datname, rl.rolname
        ORDER BY db.datname, rl.rolname
    LOOP
        RAISE NOTICE '% has % privilege(s) on database %;',
            db_r.rolname, db_r.privileges, db_r.datname;
    END LOOP;
END
$$;

内容的提问来源于stack exchange,提问作者Diogo dos Santos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 00:03:27