Oracle PL/SQL Tutorial/System Packages/DBMS JOB

Материал из SQL эксперт
Перейти к: навигация, поиск

DBMS_JOB demonstration

SQL>
SQL> CREATE TABLE run_table (message VARCHAR2(40));
Table created.
SQL>
SQL> -- create a procedure to insert rows into the test table:
SQL> CREATE OR REPLACE PROCEDURE p_run_insert IS
  2  BEGIN
  3    INSERT INTO run_table VALUES ("Execution at " ||  to_char(sysdate, "dd-mon-yy hh:mi:ss") ) ;
  4    COMMIT ;
  5  END;
  6  /
Procedure created.
SQL>
SQL> -- schedule that procedure to run every 10 seconds (approximately):
SQL> VARIABLE p_jobno number
SQL> BEGIN
  2    DBMS_JOB.SUBMIT (:p_jobno,"P_RUN_INSERT;", SYSDATE,  "SYSDATE + (10/(24*60*60))");
  3    COMMIT;  /* must commit after SUBMIT */
  4  END;
  5  /
PL/SQL procedure successfully completed.
SQL> PRINT p_jobno
   P_JOBNO
----------
       122
SQL>
SQL>
SQL> exec dbms_job.remove(1)
BEGIN dbms_job.remove(1); END;
*
ERROR at line 1:
ORA-23421: job number 1 is not a job in the job queue
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 86
ORA-06512: at "SYS.DBMS_IJOB", line 529
ORA-06512: at "SYS.DBMS_JOB", line 171
ORA-06512: at line 1

SQL>
SQL> drop table run_table;
Table dropped.
SQL>
SQL>


DBMS_JOB.SUBMIT

SQL>
SQL>
SQL> DECLARE
  2     lv_job_num NUMBER;
  3  BEGIN
  4     DBMS_JOB.SUBMIT(lv_job_num, "LOG_SOURCE;", SYSDATE, "SYSDATE + 1/24", NULL);
  5     DBMS_OUTPUT.PUT_LINE("Assigned Job #: " || lv_job_num);
  6  END;
  7  /
PL/SQL procedure successfully completed.
SQL>


Job number

SQL>
SQL>
SQL> set echo on
SQL>
SQL> create table t ( msg varchar2(80) );
Table created.
SQL>
SQL> create or replace procedure p( p_job in number, p_next_date in OUT date ) as
  2      l_next_date date default p_next_date;
  3  begin
  4      p_next_date := trunc(sysdate)+1+3/24;
  5      insert into t values ( "Next date was "" || to_char(l_next_date,"dd-mon-yyyy hh24:mi:ss") ||
  6        "" Next date IS " || to_char(p_next_date,"dd-mon-yyyy hh24:mi:ss") );
  7  end;
  8  /
Procedure created.
SQL>
SQL> variable n number
SQL>
SQL> exec dbms_job.submit( :n, "p(JOB,NEXT_DATE);" );
PL/SQL procedure successfully completed.
SQL>
SQL> select what, interval,
  2         to_char(last_date,"dd-mon-yyyy hh24:mi:ss") last_date,
  3         to_char(next_date,"dd-mon-yyyy hh24:mi:ss") next_date
  4    from user_jobs
  5   where job = :n
  6  /
WHAT
--------------------------------------------------------------------------------
INTERVAL
--------------------------------------------------------------------------------
LAST_DATE            NEXT_DATE
-------------------- --------------------
p(JOB,NEXT_DATE);
null
                     25-jul-2008 19:22:27

SQL>
SQL> exec dbms_job.run( :n );
PL/SQL procedure successfully completed.
SQL>
SQL> select * from t;
MSG
--------------------------------------------------------------------------------
Next date was "" Next date IS 26-jul-2008 03:00:00
SQL>
SQL> select what, interval,
  2         to_char(last_date,"dd-mon-yyyy hh24:mi:ss") last_date,
  3         to_char(next_date,"dd-mon-yyyy hh24:mi:ss") next_date
  4    from user_jobs
  5   where job = :n
  6  /
WHAT
--------------------------------------------------------------------------------
INTERVAL
--------------------------------------------------------------------------------
LAST_DATE            NEXT_DATE
-------------------- --------------------
p(JOB,NEXT_DATE);
null
25-jul-2008 19:22:27 26-jul-2008 03:00:00

SQL>
SQL> exec dbms_job.remove( :n );
PL/SQL procedure successfully completed.
SQL> drop table t;
Table dropped.
SQL>


Schedule the procedure to run now and every night at 3 AM:

SQL>
SQL> 
SQL> create table my_stats_table
  2  (object_name  varchar2(30),
  3   gather_date  date default sysdate);

SQL>
SQL> 
SQL> create or replace procedure gather_my_stats as
  2    olist  dbms_stats.objectTab;
  3  begin
  4    dbms_stats.gather_schema_stats(user,
  5            cascade=>TRUE,
  6            method_opt=> "AUTO",
  7            options=>"GATHER AUTO",
  8            objlist=>olist);
  9
 10    if olist.COUNT > 0 then
 11       FOR x in 1..olist.COUNT LOOP
 12           insert into my_stats_table (object_name)
 13            values(olist(x).objname);
 14       END LOOP;
 15    end if;
 16  end;
 17  /
Procedure created.
SQL>
SQL> variable job_no number
SQL>
SQL> exec dbms_job.submit(:job_no, "GATHER_MY_STATS;", SYSDATE, "TRUNC(SYSDATE+1) + 3/24")
PL/SQL procedure successfully completed.
SQL>
SQL> commit;
Commit complete.
SQL>
SQL> print job_no
    JOB_NO
----------
       141
SQL>
SQL>
SQL> drop table my_stats_table;
Table dropped.
SQL>
SQL>
SQL>


Submit a job and query the user_jobs

SQL>
SQL> create or replace procedure analyze_my_tables
  2  as
  3  begin
  4      for x in ( select table_name from user_tables )
  5      loop
  6          execute immediate
  7              "analyze table " || x.table_name || " compute statistics";
  8      end loop;
  9  end;
 10  /
Procedure created.
SQL>
SQL> declare
  2      l_job number;
  3  begin
  4      dbms_job.submit( job       => l_job,
  5                       what      => "analyze_my_tables;",
  6                       next_date => trunc(sysdate)+1+3/24,
  7                       interval  => "trunc(sysdate)+1+3/24" );
  8  end;
  9  /
PL/SQL procedure successfully completed.
SQL>
SQL> select job, to_char(sysdate,"dd-mon"),
  2                    to_char(next_date,"dd-mon-yyyy hh24:mi:ss"),
  3                    interval, what
  4  from user_jobs
  5  /
       JOB TO_CHA TO_CHAR(NEXT_DATE,"D
---------- ------ --------------------
INTERVAL
--------------------------------------------------------------------------------
WHAT
--------------------------------------------------------------------------------
        21 25-jul 01-jan-4000 00:00:00
SYSDATE + (10/(24*60*60))
P_RUN_INSERT;
        22 25-jul 01-jan-4000 00:00:00
SYSDATE + (10/(24*60*60))
P_RUN_INSERT;
       JOB TO_CHA TO_CHAR(NEXT_DATE,"D
---------- ------ --------------------
INTERVAL
--------------------------------------------------------------------------------
WHAT
--------------------------------------------------------------------------------
        41 25-jul 26-jul-2008 03:00:00
TRUNC(SYSDATE+1) + 3/24
GATHER_MY_STATS;
        61 25-jul 25-jul-2008 19:34:32
SYSDATE + 1/24
       JOB TO_CHA TO_CHAR(NEXT_DATE,"D
---------- ------ --------------------
INTERVAL
--------------------------------------------------------------------------------
WHAT
--------------------------------------------------------------------------------
LOG_SOURCE;
       101 25-jul 01-jan-4000 00:00:00
SYSDATE + (10/(24*60*60))
P_RUN_INSERT;
        82 25-jul 26-jul-2008 03:00:00
       JOB TO_CHA TO_CHAR(NEXT_DATE,"D
---------- ------ --------------------
INTERVAL
--------------------------------------------------------------------------------
WHAT
--------------------------------------------------------------------------------
trunc(sysdate)+1+3/24
analyze_my_tables;
       121 25-jul 01-jan-4000 00:00:00
SYSDATE + (10/(24*60*60))
P_RUN_INSERT;

       JOB TO_CHA TO_CHAR(NEXT_DATE,"D
---------- ------ --------------------
INTERVAL
--------------------------------------------------------------------------------
WHAT
--------------------------------------------------------------------------------
       122 25-jul 01-jan-4000 00:00:00
SYSDATE + (10/(24*60*60))
P_RUN_INSERT;
       141 25-jul 25-jul-2008 21:18:41
TRUNC(SYSDATE+1) + 3/24
GATHER_MY_STATS;
       JOB TO_CHA TO_CHAR(NEXT_DATE,"D
---------- ------ --------------------
INTERVAL
--------------------------------------------------------------------------------
WHAT
--------------------------------------------------------------------------------
       161 25-jul 25-jul-2008 19:46:13
SYSDATE + 1/24
LOG_SOURCE;
       162 25-jul 25-jul-2008 19:49:44
SYSDATE + 1/24
       JOB TO_CHA TO_CHAR(NEXT_DATE,"D
---------- ------ --------------------
INTERVAL
--------------------------------------------------------------------------------
WHAT
--------------------------------------------------------------------------------
LOG_SOURCE;
       182 25-jul 26-jul-2008 03:00:00
trunc(sysdate)+1+3/24
analyze_my_tables;

12 rows selected.


Submit a job and run

SQL>
SQL> set echo on
SQL>
SQL> create table t ( msg varchar2(20), cnt int );
Table created.
SQL>
SQL> insert into t select "from SQL*PLUS", count(*) from session_roles;
1 row created.
SQL>
SQL> variable n number
SQL>
SQL> exec dbms_job.submit(:n,"insert into t select ""from job"", count(*) from session_roles;");
PL/SQL procedure successfully completed.
SQL>
SQL> print n
         N
----------
       181
SQL>
SQL> exec dbms_job.run(:n);
PL/SQL procedure successfully completed.
SQL>
SQL> select * from t;
MSG                         CNT
-------------------- ----------
from SQL*PLUS                12
from job                      0
SQL> drop table t;
Table dropped.
SQL>


Submit job to change password

SQL> CREATE TABLE EMP(
  2      EMPNO NUMBER(4) NOT NULL,
  3      ENAME VARCHAR2(10),
  4      JOB VARCHAR2(9),
  5      MGR NUMBER(4),
  6      HIREDATE DATE,
  7      SAL NUMBER(7, 2),
  8      COMM NUMBER(7, 2),
  9      DEPTNO NUMBER(2)
 10  );
Table created.

SQL> INSERT INTO EMP VALUES(2, "Jack", "Tester", 6,TO_DATE("20-FEB-1981", "DD-MON-YYYY"), 1600, 300, 30);
1 row created.

SQL> INSERT INTO EMP VALUES(3, "Wil", "Tester", 6,TO_DATE("22-FEB-1981", "DD-MON-YYYY"), 1250, 500, 30);
1 row created.

SQL> INSERT INTO EMP VALUES(4, "Jane", "Designer", 9,TO_DATE("2-APR-1981", "DD-MON-YYYY"), 2975, NULL, 20);
1 row created.

SQL> INSERT INTO EMP VALUES(5, "Mary", "Tester", 6,TO_DATE("28-SEP-1981", "DD-MON-YYYY"), 1250, 1400, 30);
1 row created.
SQL> INSERT INTO EMP VALUES(6, "Black", "Designer", 9,TO_DATE("1-MAY-1981", "DD-MON-YYYY"), 2850, NULL, 30);
1 row created.

SQL> INSERT INTO EMP VALUES(7, "Chris", "Designer", 9,TO_DATE("9-JUN-1981", "DD-MON-YYYY"), 2450, NULL, 10);
1 row created.
SQL> INSERT INTO EMP VALUES(8, "Smart", "Helper", 4,TO_DATE("09-DEC-1982", "DD-MON-YYYY"), 3000, NULL, 20);
1 row created.

SQL> INSERT INTO EMP VALUES(9, "Peter", "Manager", NULL,TO_DATE("17-NOV-1981", "DD-MON-YYYY"), 5000, NULL, 10);
1 row created.
SQL> INSERT INTO EMP VALUES(10, "Take", "Tester", 6,TO_DATE("8-SEP-1981", "DD-MON-YYYY"), 1500, 0, 30);
1 row created.

SQL> INSERT INTO EMP VALUES(13, "Fake", "Helper", 4,TO_DATE("3-DEC-1981", "DD-MON-YYYY"), 3000, NULL, 20);
1 row created.

SQL>
SQL> create table PASSWORD_AUDIT (empno number,date_change date );

SQL>
SQL> create or replace procedure admin.reset_password(id varchar2) is
  2   v_username varchar2(30);
  3   v_job number;
  4   begin
  5       select ename into v_username from emp where empno = id and mgr = ( select empno from emp where ename = user );
  6       insert into password_audit values (id, user, sysdate);
  7       dbms_job.submit(v_job,"begin execute immediate " ||"""alter user ""||v_username||"" "||" identified by "||v_username||"""; end;");
  8   exception
  9   when no_data_found then
 10       raise_application_error(-20000, "You are not authorised to alter emp "||id);
 11   end;
 12  /

SQL> drop table emp;
Table dropped.


Use dbms_job.submit to call "execute immediate"

SQL> create table myTable (
  2   tname varchar2(30),
  3   cname varchar2(30),
  4   changed date
  5  );
Table created.
SQL>
SQL> create or replace procedure RUN_DDL(m varchar2) is
  2   pragma autonomous_transaction;
  3   begin
  4   execute immediate m;
  5   end;
  6  /
SQL>
SQL> create or replace procedure ADD_COLUMN(p_table varchar2, p_column varchar2) is
  2   v number;
  3   j number;
  4   begin
  5       insert into myTable values (p_table, p_column, sysdate);
  6       dbms_job.submit(j, "run_ddl(""alter table "||p_table||" add "||p_column||""");");
  7   end;
  8  /
Procedure created.
SQL>
SQL>
SQL> drop table myTable;
Table dropped.