Oracle'创建'触发授予权限

时间:2015-09-02 14:49:50

标签: oracle triggers privileges grant

我在数据库创建后有一个''触发器为特定模式中新创建的表提供对不同Oracle角色的选择访问。

如果我执行create table ... as select语句,然后在TOAD内的同一代码块或不同的UI中查询新表,我会遇到错误,但如果我单独运行命令,它会起作用:

create table schema1.table1 as select * from schema2.table2 where rownum < 2;

select count(*) from schema1.table1;

如果我将它们作为一个代码块执行,我得到:

  ORA-01031: insufficient privileges

如果我单独执行它们,我就不会收到错误,并且能够获得正确的计数。

AFTER CREATE触发器的示例片段

 CREATE OR REPLACE TRIGGER TGR_DATABASE_AUDIT AFTER
 CREATE OR DROP OR ALTER ON Database
 DECLARE
    vOS_User              VARCHAR2(30);
    vTerminal             VARCHAR2(30);
    vMachine              VARCHAR2(30);
    vSession_User         VARCHAR2(30);
    vSession_Id           INTEGER;
    l_jobno               NUMBER;

 BEGIN

   SELECT sys_context('USERENV', 'SESSIONID'),
          sys_context('USERENV', 'OS_USER'),
          sys_context('USERENV', 'TERMINAL'),
          sys_context('USERENV', 'HOST'),
          sys_context('USERENV', 'SESSION_USER')
   INTO   vSession_Id,
          vOS_User,
          vTerminal,
          vMachine,
          vSession_User
    FROM Dual;

    insert into schema3.event_table VALUES (vSession_Id, SYSDATE,   
    vSession_User, vOS_User, vMachine, vTerminal, ora_sysevent,  
    ora_dict_obj_type,ora_dict_obj_owner,ora_dict_obj_name);

    IF ora_sysevent = 'CREATE' THEN
       IF (ora_dict_obj_owner = 'SCHEMA1')  THEN
           IF DICTIONARY_OBJ_TYPE = 'TABLE' THEN
              dbms_job.submit(l_jobno,'sys.execute_app_ddl(''GRANT SELECT 
              ON '||ora_dict_obj_owner||'.'||ora_dict_obj_name||' TO 
              Role1,Role2'');');
           END IF;
       END IF;
    END IF;
 END;

1 个答案:

答案 0 :(得分:2)

乔布斯是异步的。你的代码不是。

暂时忽略这样一个事实:如果您动态授予特权,即世界上的某些东西正在创建新表,而不需要通过变更控制流程(此时人工审核人员会确保适当的授权)包括在内)这意味着你有一个更大的问题......

运行CREATE TABLE语句时,将触发触发器并计划运行作业。该作业在单独的会话中运行,并且无法启动,直到您的CREATE TABLE语句发出其最终的隐式提交并将控制权返回给第一个会话。最好的情况是,该作业在CREATE TABLE语句完成后运行一两秒。但它可能会更长,具体取决于允许同时运行多少个后台作业,正在运行的其他作业,Oracle的繁忙程度等等。

最简单的方法是在dbms_lock.sleepCREATE TABLE之间添加一个SELECT调用,等待一段合理的时间来运行后台作业。编写代码是微不足道的(并且有助于验证这实际上是您遇到的唯一问题),但它并非万无一失。即使你拖延了足够长的时间&#34;对于测试,您将来可能会遇到更长的延迟。更复杂的方法是查询dba_jobs,查看是否有与您刚创建的表相关的作业,如果存在循环则休眠。