08
mar
10

Tudo que você precisa saber sobre jobs

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…


7 Responses to “Tudo que você precisa saber sobre jobs”


  1. 1 jakson
    novembro 13, 2014 às 6:16 pm

    Parabéns, está sendo de muita utilidade.

  2. 2 Leandro Lister
    julho 3, 2013 às 5:34 pm

    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…

  3. 3 Josi Morais
    fevereiro 20, 2013 às 7:46 pm

    Muito bom o post. Parabéns!

  4. 4 Ândrea
    outubro 24, 2012 às 10:45 am

    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.

  5. janeiro 18, 2012 às 10:53 am

    Melhor post que eu encontrei sobre jobs. Bem escrito, com todas as informações pertinentes, porém de maneira condensada. Parabéns!

  6. janeiro 18, 2011 às 7:14 pm

    O post foi show! Ajudou pra valer. Parabéns!


Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s


%d blogueiros gostam disto: