目的:由於公司數據庫權限管理的很嚴,每次新建表后需要手動授權給相應的用戶,並且還要創建同義詞。這就很是麻煩。賬號一多就特別花時間。所以自己寫了兩個存儲過程和定時JOB來實現動態授權。
需求:A用戶訪問B用戶,A用戶可以增刪改查B用戶所有表(不包括系統表)。A是普通用戶,B用戶擁有DBA權限,所以我們不能用以下方式授權,這樣會把系統表的權限也放出去。
grant select any table to a;
grant all on b.table_name to a;
一、授予A用戶訪問B用戶現有表訪問權限
1.新建一個普通用戶A。
create user 用戶名 identified by "密碼" default tablespace 表空間 temporary tablespace temp;
授予A用戶resource/connect權限、創建私有同義詞權限。
grant create synonym to A;
grant resource,connect to A;
2.授予A用戶訪問B用戶所有表權限,另存為.sql后綴,放在Command里面執行。
select 'GRANT select, insert, update, delete ON B.'|| 表名||' to A;' from user_tables;
創建所有表的私有同義詞,在A用戶上創建
select 'create synonym '||同義詞名稱||' for B.'||表名||';' from user_tables where tablespace_name='表空間';
以上操作是針對B用戶下現有表授予A用戶訪問權限。
二、通過JOB定時調用存儲過程實現動態授權A用戶。
准備:A用戶下兩張表、兩個sequence、兩個觸發器(可有可無)、一個存儲過程、一個定時JOB。B用戶一個存儲過程、一個定時JOB
兩張表可根據自身需求增加相應的字段。
1.A用戶
A用戶表1
create table CREATE_LOG ( pid INTEGER not null, pobject VARCHAR2(400), sjc VARCHAR2(14) ); alter table CREATE_LOG add primary key (PID);
A用戶表2
create table CREATE_OBJECT ( pid INTEGER not null, sobject VARCHAR2(400), sjc VARCHAR2(14) ); alter table NEWINGS_OBJECT add primary key (PID); grant select, insert on CREATE_OBJECT to B; #授權給B用戶訪問,存儲過程里面要用到
sequence是給兩張表主鍵使用的,創建一下就好了。觸發器主要是實現主鍵自增和將空的時間戳賦值。很簡單
存儲過程
create or replace procedure create_actions is --scount number(10); snum number(10); begin declare cursor cur is select sobject from newings_object where sjc>=to_char(sysdate,'yyyymmdd'); begin for cur_result in cur loop select count(1) into snum from create_log where pobject=cur_result.sobject; if snum=0 then EXECUTE IMMEDIATE 'create synonym '||cur_result.sobject||' for B.'||cur_result.sobject; insert into create_log(pobject) values(cur_result.sobject); commit; end if; end loop; end; end;
定時JOB(A、B用戶定時JOB執行時間最好是錯開)
declare job number; BEGIN DBMS_JOB.SUBMIT( JOB => job, /*自動生成JOB_ID*/ WHAT => 'create_actions;', /*需要執行的存儲過程名稱或SQL語句*/ NEXT_DATE => sysdate+3/(24*60), /*初次執行時間-下一個3分鍾*/ INTERVAL => 'trunc(sysdate,''mi'')+1/(24*60)' /*每隔1分鍾執行一次*/ ); commit; end;
2.B用戶
存儲過程
create or replace procedure create_action is scount number(10); snum number(10); begin select count(1) into scount from user_objects where to_char(created,'yyyymmddhh24miss')>=to_char(sysdate,'yyyymmdd') and object_type='TABLE'; declare cursor cur is select object_name from user_objects where to_char(created,'yyyymmddhh24miss')>=to_char(sysdate,'yyyymmdd') and object_type='TABLE'; begin for cur_result in cur loop if scount>0 then select count(1) into snum from A.newings_object where sobject=cur_result.object_name; if snum=0 then EXECUTE IMMEDIATE 'grant select,insert,update,delete on B.'||cur_result.object_name||' to A'; --EXECUTE IMMEDIATE 'insert into A.newings_object(sobject) values('||cur_result.object_name||')'; insert into roobbin.newings_object(sobject) values(cur_result.object_name); commit; end if; end if; end loop; end; end;
定時JOB,A、B用戶定時JOB執行時間最好是錯開
declare job number; BEGIN DBMS_JOB.SUBMIT( JOB => job, /*自動生成JOB_ID*/ WHAT => 'create_action;', /*需要執行的存儲過程名稱或SQL語句*/ NEXT_DATE => sysdate+3/(24*60), /*初次執行時間-下一個3分鍾*/ INTERVAL => 'trunc(sysdate,''mi'')+1/(24*60)' /*每隔1分鍾執行一次*/ ); commit; end;
附:user_jobs主要字段說明
列名 數據類型 解釋 JOB NUMBER 任務的唯一標示號 LOG_USER VARCHAR2(30) 提交任務的用戶 PRIV_USER VARCHAR2(30) 賦予任務權限的用戶 SCHEMA_USER VARCHAR2(30) 對任務作語法分析的用戶模式 LAST_DATE DATE 最后一次成功運行任務的時間 LAST_SEC VARCHAR2(8) 如HH24:MM:SS格式的last_date日期的小時,分鍾和秒 THIS_DATE DATE 正在運行任務的開始時間,如果沒有運行任務則為null THIS_SEC VARCHAR2(8) 如HH24:MM:SS格式的this_date日期的小時,分鍾和秒 NEXT_DATE DATE 下一次定時運行任務的時間 NEXT_SEC VARCHAR2(8) 如HH24:MM:SS格式的next_date日期的小時,分鍾和秒 TOTAL_TIME NUMBER 該任務運行所需要的總時間,單位為秒 BROKEN VARCHAR2(1) 標志參數,Y標示任務中斷,以后不會運行 INTERVAL VARCHAR2(200) 用於計算下一運行時間的表達式 FAILURES NUMBER 任務運行連續沒有成功的次數 WHAT VARCHAR2(2000) 執行任務的PL/SQL塊
INTERVAL常用參數示例
每天午夜12點 ''TRUNC(SYSDATE + 1)'' 每天早上8點30分 ''TRUNC(SYSDATE + 1) + (8*60+30)/(24*60)'' 每星期二中午12點 ''NEXT_DAY(TRUNC(SYSDATE ), ''''TUESDAY'''' ) + 12/24'' 每個月第一天的午夜12點 ''TRUNC(LAST_DAY(SYSDATE ) + 1)'' 每個季度最后一天的晚上11點 ''TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3 ), ''Q'' ) -1/24'' 每星期六和日早上6點10分 ''TRUNC(LEAST(NEXT_DAY(SYSDATE, ''''SATURDAY"), NEXT_DAY(SYSDATE, "SUNDAY"))) + (6×60+10)/(24×60)'' 每3秒鍾執行一次 'sysdate+3/(24*60*60)' 每2分鍾執行一次 'sysdate+2/(24*60)' 1:每分鍾執行 Interval => TRUNC(sysdate,'mi') + 1/ (24*60) --每分鍾執行 interval => 'sysdate+1/(24*60)' --每分鍾執行 interval => 'sysdate+1' --每天 interval => 'sysdate+1/24' --每小時 interval => 'sysdate+2/24*60' --每2分鍾 interval => 'sysdate+30/24*60*60' --每30秒 2:每天定時執行 Interval => TRUNC(sysdate+1) --每天凌晨0點執行 Interval => TRUNC(sysdate+1)+1/24 --每天凌晨1點執行 Interval => TRUNC(SYSDATE+1)+(8*60+30)/(24*60) --每天早上8點30分執行 3:每周定時執行 Interval => TRUNC(next_day(sysdate,'星期一'))+1/24 --每周一凌晨1點執行 Interval => TRUNC(next_day(sysdate,1))+2/24 --每周一凌晨2點執行 4:每月定時執行 Interval =>TTRUNC(LAST_DAY(SYSDATE)+1) --每月1日凌晨0點執行 Interval =>TRUNC(LAST_DAY(SYSDATE))+1+1/24 --每月1日凌晨1點執行 5:每季度定時執行 Interval => TRUNC(ADD_MONTHS(SYSDATE,3),'q') --每季度的第一天凌晨0點執行 Interval => TRUNC(ADD_MONTHS(SYSDATE,3),'q') + 1/24 --每季度的第一天凌晨1點執行 Interval => TRUNC(ADD_MONTHS(SYSDATE+ 2/24,3),'q')-1/24 --每季度的最后一天的晚上11點執行 6:每半年定時執行 Interval => ADD_MONTHS(trunc(sysdate,'yyyy'),6)+1/24 --每年7月1日和1月1日凌晨1點 7:每年定時執行 Interval =>ADD_MONTHS(trunc(sysdate,'yyyy'),12)+1/24 --每年1月1日凌晨1點執行
參考博客:https://www.cnblogs.com/Chestnuts/p/7068456.html
大概就是這一個樣子,已親測可以使用。如有需要改進的地方請留言,謝謝!