创建新表,自动授权trigger

需求

     一个用户下三个表,开发人员不定时进行rename表名称,create原表名称 as old_table 插入少量数据,另一个业务用户需要访问该表,由于表名称rename导致经常需要手工授权。

    需求转型12.1,新创建的表,自动给开发用户进行授权,由于用户很多,因此新表对角色进行授权。

 

一、模拟场景

目标表hr.t1,业务用户scott 
SQL> create table hr.t1 as select * from hr.employees;
SQL> grant select on hr.t1 to scott;
SQL> conn scott/tiger
已连接。
SQL>
SQL> select count(*) from hr.t1;
  COUNT(*)
----------
       107
SQL> conn hr/hr
已连接。
SQL> alter table t1 rename to t1_20190612_bak;
表已更改。
SQL> create table t1 as select * from T1_20190612_BAK where rownum<=5;
表已创建。
SQL> conn scott/tiger
已连接。
SQL> select count(*) from hr.t1;
select count(*) from hr.t1
                        *1 行出现错误:
ORA-00942: 表或视图不存在

SQL> select GRANTEE,OWNER,TABLE_NAME,GRANTOR,PRIVILEGE from dba_tab_privs where table_name='T1_20190612_BAK';
GRANTEE    OWNER      TABLE_NAME      GRANTOR              PRIVILEGE
---------- ---------- --------------- -------------------- ----------
SCOTT      HR         T1_20190612_BAK HR                   SELECT
表名称rename后,授权对象自动更换为修改后的对象名称。 

 

二、测试解决方案

2.1 同义词

排除权限不足,测试同义词rename后的对象是否会跟随rename修改
SQL> grant select any table to scott;
SQL> create table t2 as select * from T1_20190612_BAK;
SQL>  conn scott/tiger
SQL> create or replace synonym t2 for hr.t2;
同义词已创建。
SQL> select count(*) from t2;
  COUNT(*)
----------
       107
SQL> alter table t2 rename to T2_20190612_BAK;
SQL>  select count(*) from t2;
 select count(*) from t2
                      *1 行出现错误:
ORA-00980: 同义词转换不再有效

SQL> select OWNER,SYNONYM_NAME,TABLE_OWNER,TABLE_NAME from dba_synonyms where table_name='T2';
OWNER      SYNONYM_NA TABLE_OWNE TABLE_NAME
---------- ---------- ---------- ------------------------------
SCOTT      T2         HR         T2
SQL>  select owner,object_name,object_type,status from dba_objects where owner='SCOTT' and object_name='T2';
OWNER      OBJECT_NAME          OBJECT_TYPE         STATUS
---------- -------------------- ------------------- -------
SCOTT      T2                   SYNONYM             VALID
SQL>  create table t2 as select * from T2_20190612_BAK where rownum<=5;
SQL> select count(*) from t2
  COUNT(*)
----------
         5

总结,本次第一个需求,使用同义词即可。但是第二个需求,如果需要对数据库新表进行授权如何操作呢?

2.2 创建触发器

http://blog.itpub.net/27042095/viewspace-741198/
http://blog.itpub.net/25016/viewspace-926488/

ORA_DICT_OBJ_NAME:用于返回DDL操作所对应的数据库对象名
ORA_DICT_OBJ_OWNER:用于返回DDL操作所对应的对象的所有者名。
ORA_DICT_OBJ_TYPE:用于返回DDL操作所对应的数据库对象的类型。

--11.2.0.4
create or replace trigger GRANT_NEWTABLE
  after create on database
DECLARE
  v_owner       varchar(30);
  v_table_name  varchar(30);
  v_object_type varchar(30);
  v_sql         varchar2(400);
begin
  v_owner       := SYS.DICTIONARY_OBJ_OWNER;
  v_table_name  := SYS.DICTIONARY_OBJ_NAME;
  v_object_type := SYS.dictionary_obj_type;
  IF (v_owner in ('HR') and v_object_type='TABLE') THEN
      v_sql := 'grant select,insert,update,delete on ' || v_owner || '.' ||v_table_name || ' TO rolea';
  DBMS_SCHEDULER.create_job (
    job_name        => 'test',
    job_type          => 'PLSQL_BLOCK',
    job_action        => 'Begin profile(''' || v_sql || '''); end ;',
    start_date        => SYSTIMESTAMP,
    repeat_interval => NULL ,
    end_date         => NULL,
    enabled           => TRUE,
    comments        => 'Run DDL from the trigger');
   end if;
   end;
   /
--12.1(由于DBMS_SCHEDULER JOB创建语法不同导致,上述11g版本输入无法执行)
create or replace trigger GRANT_NEWTABLE
  after create on database
DECLARE
  v_owner       varchar(30);
  v_table_name  varchar(30);
  v_object_type varchar(30);
  v_sql         varchar2(400);
begin
  v_owner       := SYS.DICTIONARY_OBJ_OWNER;
  v_table_name  := SYS.DICTIONARY_OBJ_NAME;
  v_object_type := SYS.dictionary_obj_type;
  IF (v_owner in ('HR') and v_object_type='TABLE') THEN
      v_sql := 'grant select,insert,update,delete on ' || v_owner || '.' ||v_table_name || ' TO rolea';
  DBMS_SCHEDULER.create_job (
    job_name        => 'test',
    job_type          => 'PLSQL_BLOCK',
    job_action        => 'begin 
 execute immediate '''||v_sql||''';
 end;',
    start_date        => SYSTIMESTAMP,
    repeat_interval => NULL ,
    end_date         => NULL,
    enabled           => TRUE,
    comments        => 'Run DDL from the trigger');
   end if;
   end;
   /

 

posted @ 2019-06-26 10:54  绿茶有点甜  阅读(342)  评论(0编辑  收藏  举报