今天在寫存儲過程的時候,發現一個很詭異的問題,存儲過程裏就一個最簡單的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