今天在写存储过程的时候,发现一个很诡异的问题,存储过程里就一个最简单的SELECT动态SQL语句。编写完成之后,执行这个存储过程,老是提示ORA-00942: table or view does not exist(ERROR -942 ORA-00942: 表或视图不存在)这个错误,可是我将这个SQL语句复制出来,单独在命令行运行,而又没有任何错误。很纠结,很纳闷,很无解,好好的一个SELECT语句,在命令行里就能够执行,放到存储过程就会出错了,怎么就不对了?ide
后来通过Google,分析和总结,最终找到了答案。为了知足有的读者就是为了找到解决问题的答案,而并不须要接下来长篇大论的分析,我这里就先给出答案。函数
角色在函数、存储过程、触发器中都是失效的,也就是说,用户从角色继承过来的权限,不能在函数、存储过程、触发器中使用。在函数、存储过程、触发器中,若是要访问其余用户的对象,须要显式地给用户授予访问的权限。oop
上面就是解决ORA-00942: table or view does not exist(ERROR -942 ORA-00942: 表或视图不存在)这个错误的答案。若是你的存储过程当中访问了其余用户的对象,而你当前登录用户的权限是以角色的形式赋予的,并不是显式赋予的,这个时候这个错误。明白人看到这里应该知道怎么解决了,若是你仍是一头雾水,请容许我继续唠叨,看看下面详细的分析。学习
我如今在个人测试库上模拟一个出现ORA-00942: table or view does not exist(ERROR -942 ORA-00942: 表或视图不存在)这个错误的场景。测试
-- SYS用户建立两个用户,并赋予DBA角色权限 create user jelly identified by 123456; create user jelly2 identified by 123456; grant dba to jelly; -- 角色赋权 grant dba to jelly2; -- 角色赋权 -- jelly用户建立表tb_student,并插入测试数据 create table tb_student(id varchar2(10), name varchar2(20), age number(3), sex varchar2(2)); insert into tb_student values('68003001', '果冻', 23, 'M'); insert into tb_student values('68003002', '史大为', 24, 'M'); insert into tb_student values('68003003', '李艳', 23, 'F'); insert into tb_student values('68003004', '郝丽', 25, 'F'); insert into tb_student values('68003005', '佟东', 24, 'M'); select * from tb_student;
如今使用jelly2用户登陆Oracle,运行如下语句:fetch
-- jelly2用户查询表tb_student select * from jelly.tb_student;
发现SQL语句能够正确的运行,这并无问题。接下来,咱们在jelly2用户下建立一个存储过程,访问jelly用户下的jelly.tb_student表,源码以下:spa
CREATE OR REPLACE PROCEDURE "JELLY2"."PRINTALLSTUDENTS" as type t_cur is ref cursor; cursor_stu t_cur; id varchar2(10); name varchar2(20); age number(3); sex varchar2(2); strSql varchar2(400); begin strSql := 'select * from jelly.tb_student'; open cursor_stu for strSql; loop fetch cursor_stu into id, name, age, sex; dbms_output.put_line('ID:' || id || ', NAME:' || name || ', AGE:' || age || ', SEX:' || sex); exit when cursor_stu%notfound or cursor_stu%notfound is null; end loop; close cursor_stu; exception when others then dbms_output.put_line('ERROR ' || SQLCODE || ' ' || SQLERRM); close cursor_stu; end;
对上面代码不是很熟悉的伙计,请参见这篇《 Oracle学习笔记——批处理利器游标 》。在命令行运行这个存储过程:命令行
SQL> set serveroutput on; SQL> execute jelly2.PRINTALLSTUDENTS ERROR -942 ORA-00942: 表或视图不存在 PL/SQL procedure successfully completed
好了,如今就模拟出现了这个错误。code
上面也说了,因为对用户jelly2赋予的是DBA角色,而角色权限在存储过程当中是失效的,因此,为了防止访问权限失效,咱们须要显示的对jelly2用户赋予访问jelly.tb_student表的权限。server
grant select any table to jelly2;
通过显示的赋权,咱们再次执行存储过程,就发现不会有问题了。
SQL> set serveroutput on; SQL> execute jelly2.PRINTALLSTUDENTS ID:68003001, NAME:果冻, AGE:23, SEX:M ID:68003002, NAME:史大为, AGE:24, SEX:M ID:68003003, NAME:李艳, AGE:23, SEX:F ID:68003004, NAME:郝丽, AGE:25, SEX:F ID:68003005, NAME:佟东, AGE:24, SEX:M ID:68003005, NAME:佟东, AGE:24, SEX:M PL/SQL procedure successfully completed