查用户权限前必须先确认当前容器,因cdb$root下查得的权限仅反映cdb层级,与pdb实际权限可能不一致;需用show con_name或sys_context确认容器,再查对应视图。

查用户权限前先确认当前容器
直接连上 Oracle 12c 默认进的是 CDB$ROOT,此时查出来的权限只反映 CDB 层级的配置,和 PDB 里实际生效的权限可能完全不一致。必须先用 show con_name 确认当前会话在哪个容器,再决定查哪套视图。
常见错误现象:在 CDB$ROOT 下执行 select * from dba_role_privs where grantee = 'SCOTT',发现没结果,但 SCOTT 在某个 PDB 里明明能建表——因为 SCOTT 是本地用户,只存在于 PDB 中,dba_role_privs 在 CDB 下默认不显示 PDB 的本地权限。
- 查当前容器:
show con_name或select sys_context('USERENV','CON_NAME') from dual - 查所有 PDB 列表及状态:
select name, open_mode from v$pdbs - 切到目标 PDB:
alter session set container = ORCLPDB1(需有SET CONTAINER权限)
查 CDB 公共用户权限用 CDB_ 视图
公共用户(用户名以 C## 开头)在 CDB 和所有已创建的 PDB 中都存在,其权限可通过 CDB_* 视图跨容器查询,但要注意授权范围是否含 container=all。
例如:在 CDB$ROOT 下查 C##ADMIN 的系统权限:
SELECT privilege, admin_option, common FROM cdb_sys_privs WHERE grantee = 'C##ADMIN';
关键点:
-
common = 'YES'表示该权限是跨容器授予的(即用了container=all) -
common = 'NO'表示只在当前容器(CDB)生效,PDB 中需单独授 -
cdb_role_privs、cdb_tab_privs同理,但只对公共用户有效
查 PDB 本地用户权限必须在对应 PDB 内执行
本地用户(如 APP_USER)只存在于单个 PDB,不能跨容器访问。若在 CDB$ROOT 查 dba_users 能看到用户名,但 dba_role_privs 或 dba_sys_privs 不会返回其记录——除非你已切换到该用户所属的 PDB。
正确做法:
- 先
alter session set container = APP_PDB - 再查:
select * from dba_sys_privs where grantee = 'APP_USER' - 或查角色:
select * from dba_role_privs where grantee = 'APP_USER' - 注意:
user_role_privs只返回当前连接用户的权限,不适用于查他人
容易踩的坑:误以为 select * from cdb_users where username = 'APP_USER' 能顺带查出其权限——cdb_users 仅存账号元信息(如 account_status),不含任何权限数据。
权限不生效?检查 PDB 是否 OPEN 且用户有表空间配额
即使权限已授予,用户仍可能报 ORA-01950: no privileges on tablespace。这不是权限缺失,而是 PDB 层级的资源限制未解除。
典型场景:
- PDB 处于
MOUNTED或READ ONLY状态 → 用户无法执行 DML - 用户被授予
CONNECT、RESOURCE,但未分配默认表空间配额 →ALTER USER app_user QUOTA UNLIMITED ON users - 用户默认表空间是
USERS,但该表空间在 PDB 中不可写(比如文件路径指向 CDB 目录)→ 报ORA-65043
真正容易被忽略的是:PDB 的表空间配额、数据文件路径、OPEN 状态这三项,和权限视图查询完全无关,但共同决定“权限是否真能用”。别只盯着 dba_sys_privs 看,得一起验证这三件事。











