select视图报错ORA-01031(oracle跨用户基表视图授权)

一、场景说明:

同事将视图(A用户)的读取权限授予C用户后,
登录C用户后,读取该视图报错ORA-01031: 权限不足

二、遇到该问题时,我的处理思路:

1、首先该报错一般是创建视图会报,因为缺少CREATE VIEW权限,但读取视图报这个错误却属于非正常情况
2、忽略原理,首先尝试解决问题,询问该视图是否问跨用户视图,得到确认
3、询问是否所有视图相关基表的读取权限都赋予了C用户,得到肯定答复
      并且得到反馈为,基表赋权后,直接通过视图的创建语句(select)进行读取可以获得结果,但直接读取视图依然报ORA-01031
4、当时无现成方案,决定赋予C用户select any table系统权限临时处理

三、问题诊断思路:

1、这种问题算诡异问题的一种。因为理论上,赋予视图读取权限要么成功后可以正常读取,要么因为权限不足报错ORA-00990: 权限缺失或无效。
      如果报00990 一般为缺少其他用户相关基表的 with grant option,重新赋予读取权限并增加 with grant option解决即可。
2、询问同事是否使用A用户进行授权的,得到使用SYS用户进行直接授权的。怀疑与直接用SYS用户授权有关

四、问题场景模拟还原:

思路说明:创建A,B,C用户。A用户创建视图V_a,并包含B用户的dept表。通过sys用户将该视图的select权限赋予C用户。

1、创建用户

SQL> create user a identified by a account unlock;

用户已创建。

SQL> create user b identified by b account unlock;

用户已创建。

SQL> create user c identified by c account unlock;

用户已创建。

SQL> grant connect,resource to a,b,c;

授权成功。

2、创建表及相关视图

B用户
SQL> create table a.emp as select * from scott.emp;

表已创建。

SQL> create table b.dept as select * from scott.dept;

表已创建。

SQL> create view a.v_a as select a.* from  a.emp a ,b.dept b where a.deptno=b.deptno;
create view a.v_a as select a.* from  a.emp a ,b.dept b where a.deptno=b.deptno
                                                 *
第 1 行出现错误:
ORA-01031: 权限不足

SQL> grant select on b.dept to a;

授权成功。

SQL> create view a.v_a as select a.* from  a.emp a ,b.dept b where a.deptno=b.deptno;

视图已创建。

3、错误重现

首先我们通过A用户直接授权,看会出现什么情况

SQL> conn a/a
已连接。
SQL> grant select on v_a to c;
grant select on v_a to c
                *
第 1 行出现错误:
ORA-01720: 不存在 'B.DEPT' 的授权选项

这里明确提醒,a用户只有dept的select权限,但没有将该表的select权限赋予别人的能力
现在通过sys用户授权看看,看是否可以成功?。

SQL> conn / as sysdba
已连接。
SQL> grant select on a.v_a to c;
授权成功。

这里显示授权成功了,我们读取看看

SQL> conn c/c
已连接。
SQL> select * from a.v_a
  2  ;
select * from a.v_a
                *
第 1 行出现错误:
ORA-01031: 权限不足

错误重现。

五、解决方案

SQL> conn / as sysdba
已连接。
SQL> grant select on b.dept to a with grant option;

授权成功。

SQL> conn c/c
已连接。
SQL>  select count(*) from a.v_a;

  COUNT(*)
----------
        14

问题处理完毕,但这不算结束。
因为这里是模拟环境,很容易就找到夸用户表,如果生产环境出现跨越多个用户,多个表,难道一个一个找?现在寻找脚本解决它。
编写脚本如下:

select 'grant select on '||referenced_owner||'.'||REFERENCED_NAME||' to '||owner||'with grant option;' from DBA_DEPENDENCIES where owner=upper('&viewowner') and name=upper('&viewname') and type='VIEW' and referenced_type='TABLE';
将该语句获得的结果通过dba用户执行即可。

涉及到两个变量
变量1、viewowner输入视图的拥有者
变量2、viewname 输入视图名称

六、整体演示(连脚本功能)

1、初始化环境

SQL> drop user a cascade;

用户已删除。

SQL> drop user b cascade;

用户已删除。

SQL> drop user c cascade;

用户已删除。

SQL> create user a identified by a account unlock;

用户已创建。

SQL> create user b identified by b account unlock;

用户已创建。

SQL> create user c identified by c account unlock;

用户已创建。

SQL>
SQL> grant connect,resource to a,b,c;

授权成功。

SQL> create table a.emp as select * from scott.emp;

表已创建。

SQL> create table b.dept as select * from scott.dept;

表已创建。

SQL> grant select on b.dept to a;

授权成功。

SQL>  create view a.v_a as select a.* from  a.emp a ,b.dept b where a.deptno=b.deptno;

视图已创建。

SQL> grant select on a.v_a to c;

授权成功。

SQL> conn c/c
已连接。
SQL> select count(*) from a.v_a;
select count(*) from a.v_a
                       *
第 1 行出现错误:
ORA-01031: 权限不足

通过脚本处理该问题

SQL> conn / as sysdba
已连接。
SQL> select 'grant select on '||referenced_owner||'.'||REFERENCED_NAME||' to &&viewowner with grant option;' from DBA_DE
PENDENCIES where name=upper('&viewname') and owner=upper('&&viewowner') and type='VIEW' and referenced_type='TABLE';
输入 viewowner 的值:  a
输入 viewname 的值:  v_a
原值    1: select 'grant select on '||referenced_owner||'.'||REFERENCED_NAME||' to &&viewowner with grant option;' from
DBA_DEPENDENCIES where name=upper('&viewname') and owner=upper('&&viewowner') and type='VIEW' and referenced_type='TABLE
'
新值    1: select 'grant select on '||referenced_owner||'.'||REFERENCED_NAME||' to a with grant option;' from DBA_DEPEND
ENCIES where name=upper('v_a') and owner=upper('a') and type='VIEW' and referenced_type='TABLE'

'GRANTSELECTON'||REFERENCED_OWNER||'.'||REFERENCED_NAME||'TOAWITHGRANTOPTION;'
--------------------------------------------------------------------------------
grant select on A.EMP to a with grant option;
grant select on B.DEPT to a with grant option;

SQL> grant select on A.EMP to a with grant option;

授权成功。

SQL> grant select on B.DEPT to a with grant option;

授权成功。

检查结果

SQL> conn c/c
已连接。
SQL> select count(*) from a.v_a;

  COUNT(*)
----------
        14

This case end;

Thank for watching;

====================================================
勤学如春起之苗,不见其增日有所长。辍学如磨刀之石,不见其损日有所亏

Email: [email protected]
QQ: 88285879

你可能感兴趣的:(select视图报错ORA-01031(oracle跨用户基表视图授权))