只执行 GRANT CREATE VIEW TO scott 报 ORA-01031,是因为创建视图需底层表的显式 SELECT 权限,角色权限在编译时不可用,且必须验证 SESSION_PRIVS 中实际生效的权限。

直接给 CREATE VIEW 权限通常不够,必须同时解决对象访问权限和角色生效问题。
为什么只执行 grant create view to scott 还是报 ORA-01031
因为创建视图不只是“建个壳”,它依赖底层表的可读性。即使你有 CREATE VIEW 权限,如果视图定义里引用了其他 schema 的表(比如 SELECT * FROM hr.employees),而当前用户没有对 hr.employees 的 SELECT 权限,编译时就会失败——Oracle 在创建阶段就做对象存在性和权限校验。
- 错误不是出在“建视图”动作本身,而是出在“解析视图定义中的对象”这一步
-
CREATE VIEW是系统权限,但访问别人表是对象权限,两者不自动关联 - 如果用的是角色(如
SELECT_CATALOG_ROLE)间接获得SELECT权限,在视图编译上下文中默认不可用(PL/SQL 安全模型限制)
SELECT 权限必须显式授予,不能靠角色
假设你要在 scott 用户下创建一个基于 hr.departments 的视图:
CREATE OR REPLACE VIEW dept_view AS SELECT * FROM hr.departments;
那么仅靠 GRANT SELECT_CATALOG_ROLE TO scott 或 SET ROLE SELECT_CATALOG_ROLE 是无效的——视图编译时不会继承角色权限。
- 必须执行:
GRANT SELECT ON hr.departments TO scott - 如果视图跨多个 schema,每个被引用的表/视图都要单独授权
- 不要用
SELECT ANY TABLE,它绕过对象级控制,且在生产环境属于高危权限 - 若目标表属同 schema(如
scott.emp),则无需额外授权,但需确认scott对自身对象有SELECT(默认有)
检查权限是否真正在会话中生效
授完权不代表立刻可用,尤其是通过角色授予的权限,在新连接中默认未启用。
- 登录后执行:
SELECT * FROM SESSION_ROLES,确认所需角色出现在结果中;若没有,运行SET ROLE role_name - 更可靠的方式是查
SELECT * FROM SESSION_PRIVS,这里列出的是当前会话**实际能用**的系统权限(不含角色间接带来的) - 如果是 JDBC、cx_Oracle 等程序连接,注意连接字符串是否带
currentSchema=xxx,这会改变权限查找上下文 - 在 PL/SQL Developer 或 SQL Developer 中,新建窗口 ≠ 新会话,可能缓存旧权限状态,建议重启连接或显式
DISCONNECT/CONNECT
复杂视图场景:涉及数据字典或远程对象
当你创建的视图引用 DBA_* 视图(如 DBA_TABLES)或同义词、DBLINK 对象时,权限链更长。
- 查数据字典需
SELECT ANY DICTIONARY(慎用)或更细粒度的SELECT权限(如GRANT SELECT ON sys.dba_tables TO scott) - 同义词本身不解决权限问题,它只是别名;仍需对原对象授权
- 通过 DBLINK 查询远程库表,本地用户还需有
CREATE DATABASE LINK权限,并确保远程库已向本地用户开放对应对象权限 - 使用
WITH CHECK OPTION或嵌套视图时,所有中间层视图也必须对当前用户可读
最容易被忽略的是:权限授完后没验证会话上下文是否激活,或者误以为“有角色=有权限”。真实环境里,SESSION_PRIVS 才是唯一可信依据。


















