Para criar jobs no Banco de Dados em versões 9i ou inferiores, podemos utilizar a package DBMS_JOB.
Vamos simplificar este assunto indo direto ao ponto que você precisa. Para isso, conheca a package DBMS_JOB:
DBMS_JOB.SUBMIT()
DBMS_JOB.REMOVE()
DBMS_JOB.CHANGE()
DBMS_JOB.WHAT()
DBMS_JOB.NEXT_DATE()
DBMS_JOB.INTERVAL()
DBMS_JOB.RUN()
DBMS_JOB.SUBMIT()
—————–
Existe atualmente duas versões, SUBMIT() e ISUBMIT()
PROCEDURE DBMS_JOB.SUBMIT( job OUT BINARY_INTEGER, what IN VARCHAR2, next_date IN DATE DEFAULT SYSDATE, interval IN VARCHAR2 DEFAULT 'NULL', no_parse IN BOOLEAN DEFAULT FALSE); PROCEDURE DBMS_JOB.ISUBMIT( job IN BINARY_INTEGER, what IN VARCHAR2, next_date in DATE DEFAULT SYSDATE interval IN VARCHAR2 DEFAULT 'NULL', no_parse in BOOLEAN DEFAULT FALSE);
A diferença entre ISUBMIT e SUBMIT é que ISUBMIT especifica um número para o job enquanto que SUBMIT retorna o número gerado
pela package DBMS_JOB.
Visualizando os jobs submitados:
——————————-
select job,last_date,next_date,interval,substr(what, 1, 50) from dba_jobs;
Criando um job:
————–
O número do job (se você estiver usando o SUBMIT()) será originado da sequence SYS.JOBSEQ
Para exemplificarmos a criação e manipulação de jobs, vamos utilizar uma procedure como mostrada a seguir Lembrando que é
apenas para exemplificação:
create or replace procedure teste is begin dbms_output.put_line('Oi Eder!'); end; /
Examplo 1:
———-
declare variable numero_job number; begin DBMS_JOB.SUBMIT(:numero_job, 'teste;', Sysdate, 'Sysdate+1'); commit; end; / DECLARE numero_job NUMBER; BEGIN DBMS_JOB.SUBMIT(job => numero_job,what => 'teste;',next_date => SYSDATE,interval => 'SYSDATE+1/24'); COMMIT; END; /
Supondo que você tenha criado esse job as 10:00. Então, a próxima vez que ele rodará, será as 11:00.
Examplo 2:
———-
declare variable numero_job number; begin DBMS_JOB.SUBMIT(:numero_job, 'teste;', LAST_DAY(SYSDATE+1), 'LAST_DAY(ADD_MONTHS(LAST_DAY(SYSDATE+1),1))'); commit; end; /
Examplo 3:
———-
VARIABLE numero_job NUMBER BEGIN DBMS_JOB.SUBMIT(:numero_job,'DBMS_DDL.ANALYZE_OBJECT(''TABLE'',''CHARLIE'',''X1'',''ESTIMATE'',NULL,50);',SYSDATE,'SYSDATE + 1'); COMMIT; END; / PRINT numero_job NUMERO_JOB
———-
45682
Examplo 4: este job foi agendado para rodar de hora em hora
———————————————————–
DECLARE numero_job NUMBER; BEGIN DBMS_JOB.SUBMIT(job => numero_job,what => 'begin space_logger; end;',next_date => SYSDATE,interval => 'SYSDATE+1/24'); COMMIT; END; /
Example 5: Examplos de intervalos
———————————
‘SYSDATE + 7’ :extamente sete dias da última execução
‘SYSDATE + 1/48’ :cada meia hora
‘NEXT_DAY(TRUNC(SYSDATE), ”MONDAY”) + 15/24’ :toda segunda-feira as 15:00
‘NEXT_DAY(ADD_MONTHS(TRUNC(SYSDATE, ”Q”), 3), ”THURSDAY”)’ :primeira quinta-feira de cada trimestre
‘TRUNC(SYSDATE + 1)’ :todo dia a meia noite
‘TRUNC(SYSDATE + 1) + 8/24’ :todo dia as 08:00
‘NEXT_DAY(TRUNC(SYSDATE ), “TUESDAY” ) + 12/24’ :toda terça-feira ao meio dia
‘TRUNC(LAST_DAY(SYSDATE ) + 1)’ :primeiro dia de cada mês a meia noite
‘TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3 ), ‘Q’ ) – 1/24′ :último dia de cada trimestre as 23:00
‘NEXT_DAY(SYSDATE, “FRIDAY”) ) ) + 9/24’ :cada segunda,quarta e sexta as 09:00
———————————————————————————
Examplo 6:
———-
Você tem esta procedure
create or replace procedure teste as id_next number; begin select max(id) into id_next from iftest; insert into iftest(id) values(id_next+1); commit; end; /
Suponha que, em 16 de julho as 09:26 você execute:
variable numero_job number; begin DBMS_JOB.SUBMIT(:numero_job, 'teste;', LAST_DAY(SYSDATE+1), 'LAST_DAY(ADD_MONTHS(LAST_DAY(SYSDATE+1),1))'); commit; end; / select job, to_char(this_date,'DD-MM-YYYY;HH24:MI'), to_char(next_date, 'DD-MM-YYYY;HH24:MI') from dba_jobs; JOB TO_CHAR(THIS_DAT TO_CHAR(NEXT_DAT ---------- ---------------- ---------------- 25 07-03-2010;09:26
Suponha que, em 16 de julho as 09:38 você execute:
variable numero_job number; begin DBMS_JOB.SUBMIT(:numero_job, 'teste;', LAST_DAY(SYSDATE)+1, 'LAST_DAY(ADD_MONTHS(LAST_DAY(SYSDATE+1),1))'); commit; end; / select job, to_char(this_date,'DD-MM-YYYY;HH24:MI'), to_char(next_date, 'DD-MM-YYYY;HH24:MI') from dba_jobs; JOB TO_CHAR(THIS_DAT TO_CHAR(NEXT_DAT ---------- ---------------- ---------------- 25 31-07-2004;09:26 26 01-08-2004;09:38
Suponha que, em 16 de julho as 09:41 você execute:
variable numero_job number; begin DBMS_JOB.SUBMIT(:numero_job, 'teste;', SYSDATE, 'LAST_DAY(ADD_MONTHS(LAST_DAY(SYSDATE+1),1))'); commit; end; / select job, to_char(this_date,'DD-MM-YYYY;HH24:MI'), to_char(next_date, 'DD-MM-YYYY;HH24:MI') from dba_jobs; JOB TO_CHAR(THIS_DAT TO_CHAR(NEXT_DAT ---------- ---------------- ---------------- 27 31-08-2004;09:41 25 31-07-2004;09:26 26 01-08-2004;09:39
Suponha que, em 16 de julho as 09:46 você execute:
variable numero_job number; begin DBMS_JOB.SUBMIT(:numero_job, 'teste;', SYSDATE, 'TRUNC(LAST_DAY(SYSDATE + 1/24 ) )'); commit; end; / select job, to_char(this_date,'DD-MM-YYYY;HH24:MI'), to_char(next_date, 'DD-MM-YYYY;HH24:MI') from dba_jobs; JOB TO_CHAR(THIS_DAT TO_CHAR(NEXT_DAT --------- ---------------- ---------------- 27 31-08-2004;09:41 28 31-07-2004;00:00 25 31-07-2004;09:26 29 31-07-2004;00:00
————————————————————————————–
variable numero_job number; begin DBMS_JOB.SUBMIT(:numero_job, 'teste;', null, 'TRUNC(LAST_DAY(SYSDATE ) + 1)' ); commit; end; /
Na definição do job, use aspas simples para determinar o que será executado e sempre coloque “;” no final da definição, como
mostrado nos exemplos.
DBMS_JOB.REMOVE()
—————–
Removendo um Job da fila de execução
Para remover um job da fila, utilize a procedure REMOVE, da package DBMS_JOB.
A seguinte declaração remove o job de número 14144 da fila de execução:
BEGIN DBMS_JOB.REMOVE(14144); END; /
DBMS_JOB.CHANGE()
—————–
Neste exemplo, o job com o número 14144 é alterado para executar a cada três dias:
BEGIN DBMS_JOB.CHANGE(14144, NULL, NULL, 'SYSDATE + 3'); END; /
Se você especificar NULL para WHAT, NEXT_DATE ou INTERVAL quando você executar essa procedure, significa que você NÃO quer
alterar esses parâmetros, ou seja, eles ficarão inalterados (com a configuração anterior).
DBMS_JOB.WHAT()
—————
Você pode alterar a definição de um job executando a procedure DBMS_JOB.WHAT.
O seguint exemplo altera a definição do job com número 14144:
BEGIN DBMS_JOB.WHAT(14144,'DBMS_DDL.ANALYZE_OBJECT(''TABLE'',''HR'', ''DEPARTMENTS'',''ESTIMATE'', NULL, 50);'); END; /
DBMS_JOB.NEXT_DATE()
——————–
Você pode alterar a data da próxima execução de um job. Para isso, basta executar a procedure DBMS_JOB.NEXT_DATE:
BEGIN DBMS_JOB.NEXT_DATE(14144, SYSDATE + 4); END; /
DBMS_JOB.INTERVAL()
——————-
O seguinte exemplo ilustra a alteração do intervalo de execução. Para isso foi utilizado a procedure DBMS_JOB.INTERVAL:
BEGIN DBMS_JOB.INTERVAL(14144, 'NULL'); END; /
execute dbms_job.interval(<job number>,’SYSDATE+(1/48)’);
Neste caso, o job não será executado novamente após ele executar com sucesso e ainda será excluído da fila de execução de
jobs.
DBMS_JOB.BROKEN()
—————–
Um job é rotulado como broken ou non-broken. O oracle não tenta executar jobs rotulados como broken.
Examplo:
BEGIN DBMS_JOB.BROKEN(10, TRUE); END; / Examplo: O seguinte exemplo marca o job 14144 como not broken e seta a próxima data de execução para a próxima segunda-feira: BEGIN DBMS_JOB.BROKEN(14144, FALSE, NEXT_DAY(SYSDATE, 'MONDAY')); END; / Examplo: exec DBMS_JOB.BROKEN( V_JOB_ID, true);
Examplo:
select JOB into V_JOB_ID from DBA_JOBS where WHAT like '%SONERA%'; DBMS_SNAPSHOT.REFRESH( 'SONERA', 'C'); DBMS_JOB.BROKEN( V_JOB_ID, false);
correção de jobs brokens
————————
CREATE OR REPLACE PROCEDURE corrige_job AS /* || executa DBMS_JOB.BROKEN para tentar e seta || qualquer job broken como unbroken */ /* seleciona os cursores de jobs brokens do usuário*/ CURSOR broken_jobs_cur IS SELECT job FROM user_jobs WHERE broken = 'Y'; BEGIN FOR job_rec IN broken_jobs_cur LOOP DBMS_JOB.BROKEN(job_rec.job,FALSE); END LOOP; END job_fixer;
DBMS_JOB.RUN()
—————
BEGIN DBMS_JOB.RUN(14144); END; /
Além disso, ainda podemos monitorar os jobs com a view DBA_JOBS. Vejam as colunas desta view:
JOB Identificador do Job. LOG_USER Usuário que estava logado quando o job foi criado. PRIV_USER USER cujo privilégio default privileges é aplicado no job. SCHEMA_USER Essa coluna é interessante.... Se nessa coluna estiver o valor JOSE e o job executar, por exemplo, uma procedure chamada CALCULA_VALOR, o Oracle irá executar JOSE.CALCULA_VALOR. LAST_DATE Última vez, em data, na qual o job foi executado com SUCESSO! LAST_SEC Por incrível que pareça, o mesmo que LAST_DATE. THIS_DATE Se esta coluna estiver nula significa que o job não está sendo executado mas se contiver alguma data, significa que esse é o momento em que o job iniciou e ainda está sendo executado. THIS_SEC De novo, é o mesmo que THIS_DATE. NEXT_DATE Próxima data em que o job irá executar. NEXT_SEC Eu não sei porque mas, novamente, é o mesmo que NEXT_DATE. TOTAL_TIME Tempo total gasto, desde o princípio, pelo sistema, neste job. BROKEN Se Y, o job não está executando. INTERVAL Uma função de data que define o NEXT_DATE. Essa coluna determina a frequencia em que o job será executado. FAILURES Exibe quantas vezes o job executou e falhou desde a última execução bem sucedida. WHAT O que esse job irá executar. Pode ser um bloco anônimo, uma procedure ou uma package. NLS_ENV Parâmetros de sessão descrevendo o ambiente NLS para o job. MISC_ENV Outros parâmetros de sessão para a execução do job. INSTANCE ID da instância que pode executar o job. O default é 0 mas em ambiente clusterizado, isso pode mudar.
E como podemos alterar um job de outro usuário? Por exemplo, executamos a seguinte consulta: select job, log_user from dba_jobs e obtemos uma linha com 123 e JOSE. Isso significa que o número do job é 123 e ele pertence ao schema JOSE. Mas suponhamos que estamos conectados no schema MARIA que tem permissão de DBA, para simplificar, e tentamos alterar o NEXT_DATE desse job. Certamente, a primeira tentativa seria executar o comando:
exec dbms_job.next_date(job => 123,next_date => to_date('06/10/2011 01:00','dd/mm/rrrr hh24:mi'));
Mas teremos o seguinte erro:
ERROR at line 1: ORA-23421: job number 123 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
Esse erro nos diz que o usuário que executou o comando não é dono do job. E agora José? Como eu posso alterar o job do schema JOSE se, supostamente não tenho acesso à esse schema, por um motivo qualquer? Não se desespere pois um pacote não documentado está prestes à surgir, é o DBMS_IJOB. Esse cara pode fazer tudo……
Espero que tenha ajudado…
BOM DIA ….COMO DESABILITAR UM JOB NO DEVELOPER?
Parabéns, está sendo de muita utilidade.
Legal, agora eu preciso dar um jeito de fazer uma tela em apex que o “usuario” vai parametrizar o job com a data de inicio e fim…
Muito bom o post. Parabéns!
Nossa, adorei, muito bom mesmo. Parabéns!
Gostaria de saber se existe a possibilidade de criar um JOB para executar mais de uma tarefa no mesmo job. É que preciso criar várias visões materializadas para executar a cada 12horas, so q tenho configurado o parametro job_queue com o valor 10, ou seja, posso criar até 10 Jobs no meu banco. Sei que isto é ajustável, mas queria verificar se tem como eu criar um Job para executar mais de uma tarefa, se tiver, você poderia me ajudar a montar, colocando alguns exemplos.
Melhor post que eu encontrei sobre jobs. Bem escrito, com todas as informações pertinentes, porém de maneira condensada. Parabéns!
O post foi show! Ajudou pra valer. Parabéns!