如何删除非当前用户下的JOB

Oracle没有对JOB设置相应的权限,任何用户都可以使用DBMS_JOB包建立自己的JOB。也正是因为没有权限的限制,所以使用DBMS_JOB包无法删除其他用户下的JOB。

因此一直认为Oracle无法删除其他用户下的JOB,最多只能在删除用户的时候级联删除。看了论坛中jametong的回复,感觉Oracle中真的很少有什么东西不能做,而主要是你是否知道或能否想到的。受jametong的启发,又总结出一种删除其他用户下JOB的方法。

下面总结了这两种方法,一个是通过Undocument的包DBMS_IJOB,这种情况下需要DBMS_IJOB的执行权限。另一种方法需要CREATE ANY PROCEDURE和EXECUTE ANY PROCEDURE的权限。

 


SQL> conn yangtk/yangtk@test4
已连接。
SQL> select job, priv_user, what from user_jobs;

未选定行

SQL> declare
  2  v_job number;
  3  begin
  4  dbms_job.submit(v_job, 'null;', sysdate, 'sysdate + 1');
  5  commit;
  6  end;
  7  /

PL/SQL 过程已成功完成。

SQL> select job, priv_user, what from user_jobs;

       JOB PRIV_USER                      WHAT
---------- ------------------------------ ---------------------
        84 YANGTK                         null;

SQL> conn /@test4 as sysdba
已连接。
SQL> select job, priv_user, what from dba_jobs;

       JOB PRIV_USER                      WHAT
---------- ------------------------------ ----------------------
        84 YANGTK                         null;

SQL> exec dbms_job.remove(84);
BEGIN dbms_job.remove(84); END;

*
ERROR 位于第 1 行:
ORA-23421: 作业编号84在作业队列中不是一个作业
ORA-06512: 在"SYS.DBMS_SYS_ERROR", line 86
ORA-06512: 在"SYS.DBMS_IJOB", line 529
ORA-06512: 在"SYS.DBMS_JOB", line 171
ORA-06512: 在line 1

即使是SYS用户也无法通过DBMS_JOB包删除其他用户下的JOB。但是可以通过其他两种方法来实现。

方法一:通过DBMS_IJOB包。

SQL> create user a identified by a;

用户已创建

SQL> grant create session to a;

授权成功。

SQL> grant execute on dbms_ijob to a;

授权成功。

SQL> conn a/a@test4
已连接。
SQL> select job, priv_user, what from all_jobs;

未选定行

SQL> exec dbms_job.remove(84);
BEGIN dbms_job.remove(84); END;

*
ERROR 位于第 1 行:
ORA-23421: 作业编号84在作业队列中不是一个作业
ORA-06512: 在"SYS.DBMS_SYS_ERROR", line 86
ORA-06512: 在"SYS.DBMS_IJOB", line 529
ORA-06512: 在"SYS.DBMS_JOB", line 171
ORA-06512: 在line 1


SQL> exec sys.dbms_ijob.remove(84);

PL/SQL 过程已成功完成。

SQL> commit;

提交完成。

SQL> conn yangtk/yangtk@test4
已连接。
SQL> select job, priv_user, what from user_jobs;

未选定行

方法二:通过建立其他用户下的存储过程来执行dbms_job包。

SQL> show user
USER 为"YANGTK"
SQL> declare
  2  v_job number;
  3  begin
  4  dbms_job.submit(v_job, 'null;', sysdate, 'sysdate + 1');
  5  commit;
  6  end;
  7  /

PL/SQL 过程已成功完成。

SQL> select job, priv_user, what from user_jobs;

       JOB PRIV_USER                      WHAT
---------- ------------------------------ --------------------
        85 YANGTK                         null;

SQL> conn /@test4 as sysdba
已连接。
SQL> grant create session to b identified by b;

授权成功。

SQL> grant create any procedure, execute any procedure to b;

授权成功。

SQL> conn b/b@test4
已连接。
SQL> create procedure yangtk.p_execute(p_str in varchar2) as
  2  begin
  3  execute immediate p_str;
  4  end;
  5  /

过程已创建。

注意,如果需要以CREATE OR REPLACE方式创建存储过程,还需要ALTER ANY PROCEDURE权限。

SQL> begin
  2  yangtk.p_execute('begin dbms_job.remove(85); commit; end;');
  3  end;
  4  /

PL/SQL 过程已成功完成。

SQL> conn yangtk/yangtk@test4
已连接。
SQL> select job, priv_user, what from user_jobs;

未选定行

第二种方法还支持删除其他用户下数据库链的功能。

SQL> create database link yangtk.yangtingkun;

数据库链接已创建。

SQL> conn /@test4 as sysdba
已连接。
SQL> col db_link format a40
SQL> select owner, db_link from dba_db_links where owner = 'YANGTK';

OWNER                          DB_LINK
------------------------------ ---------------------------
YANGTK                         YANGTK.YANGTINGKUN

SQL> drop database link yangtk.yangtingkun;
drop database link yangtk.yangtingkun
                   *
ERROR 位于第 1 行:
ORA-02024: 未找到数据库链接


SQL> drop database link yangtk.yangtk.yangtingkun;
drop database link yangtk.yangtk.yangtingkun
                   *
ERROR 位于第 1 行:
ORA-02024: 未找到数据库链接


SQL> conn b/b@test4
已连接。
SQL> exec yangtk.p_execute('drop database link yangtk.yangtingkun')

PL/SQL 过程已成功完成。

SQL> conn yangtk/yangtk@test4
已连接。
SQL> select * from user_db_links;

未选定行

需要注意的是,DBMS_IJOB包允许建立、删除、修改任意用户的JOB,这个权限很大,应当慎重授权。而第二种方法需要的CREATE ANY PROCEDURE和EXECUTE ANY PROCEDURE更要小心,不应该授权给除DBA以外的其他用户。

 

你可能感兴趣的:(Oracle,故障处理)