起因
為什么會有這篇文章呢? 因為最近在做項目的時候遇到一個問題...實際生產環境中程序datasource登陸的Oracle數據庫用戶user1不是我們創建的.這個用戶沒有訪問我們業務表的權限(因為和其他公司合作,用user1去訪問它們的數據)....我們開發中用到的用戶user2是我們自己創建的有相關業務表的權限,而這個用戶user2在實際生產環境中也是有的...
所以我要做的事情就是把我們user2的相關表的查詢權限賦值給user1就行了...實際解決那個問題的時候我是手動寫SQL賦權限的...因為依賴的表不多...
這個問題解決以后我思考了下,其實這個問題簡化抽象一下的話就是問 如何能夠批量把一個用戶下的所有表的select權限賦值給另外一個用戶
這個問題我百度了下,有一些解決辦法,比如可以將表的權限賦值給public..但是這些都不是特別好的(因為這樣隨便哪個用戶都能訪問你的業務表,很不安全)....
解決辦法
已知
首先應該整理一下我已知的知識,然后再去想辦法...我已知的事情是:
1.賦單張表的select權限的SQL是 grant select on user1.table1 to user2
2.要找出user1下的所有表賦權限,那表名肯定不是寫死的.而是通過SQL動態獲取的
3.要通過SQL獲取user1下的所有表名肯定需要dba的權限,通過查詢dba的什么什么表才能獲取..
解決
通過各種百度與實踐..我找到了1個視圖,dba_tables.查詢這個視圖可以得到一個用戶下的所有表..
我就不啰嗦了,直接貼代碼..
1 create or replace procedure test(v_from in varchar2, v_to in varchar2) is 2 v_sql varchar2(1000); 3 cursor v_cur is 4 select t.* from dba_tables t where t.OWNER = v_from; 5 6 begin 7 for v_row in v_cur loop 8 v_sql := 'grant select on ' || v_from || '.' || v_row.table_name || 9 ' to ' || v_to; 10 execute immediate v_sql; 11 end loop; 12 end test;
解釋如下:
我創建了這個test存儲過程,它有2個入參,v_from和v_to,表示我准備將v_from用戶下的所有表的select權限賦值給v_to用戶,然后test存儲過程里面有一個游標v_cur,這個游標就是為了找出用戶v_from下的所有表...這個游標是通過dba_tables視圖加上where條件過濾用戶名得到的..
得到這個v_from用戶下的所有表以后我打算構造一個SQL,用來賦權限,這個SQL就是保存在v_sql中..
在loop中,每次loop都可以得到1個v_from用戶的表名,存儲在v_row.table_name中.通過拼接字符串可以得到v_sql授權語句.
運行這個授權語句..然后繼續下一次的loop得到新的表名.
以上便是我的思路...
測試
我新建了用戶JYZ1和JYZ2,都是普通用戶,然后我在JYZ1下新建了2張表,t1和t2....JYZ2是沒有權限select的...(如下圖,dba_tab_privs可以查詢一張表授權給過哪些用戶,圖中沒有記錄表示JYZ1用戶下的所有表都沒有授權給過其他用戶)
運行存儲過程(我是用system connect as sysdba執行的)
運行test以后可以發現現在JYZ2有JYZ1的表的權限了.
小結
通過我上面那個test存儲過程可以將一個用戶下的所有表的select權限賦值給另外一個用戶,當然如果要增加其他權限,比如update什么的,可以直接修改SQL,也是比較方便的...
另外需要特別注意的就是這個存儲過程我用system connect as normal的時候不知到為什么一直編譯不通過,即使system確實是有dba的權限的...而system connect as dba的時候才可以執行..不明白為什么....