Nos últimos tempos tenho trabalhado com jobs em base de dados Oracle.
Mesmo que a base de dados utilizada fosse a 10g é ainda utilizado o DBMS_JOB. Recentemente li o [1] e descobri o DBMS_SCHEDULER.
Dou dois
exemplos de dificuldades que senti com o DBMS_JOB:
- definir o intervalo de execução: fraca legibilidade, demasiado código para conseguir o agendamento desejado;
 - configurar o deploy de um job: apenas um campo númérico identifica univocamente o job na lista.
 
Neste post vou falar sobre o segundo ponto: o deploy de um job.
Oracle 9i: o DBMS_JOB
Na versão 9i a gestão de jobs é feita com o package DBMS_JOB.
Eis o script de deploy mais simples:
DECLARE
  V_JOB NUMBER;
BEGIN
  DBMS_JOB.SUBMIT(
		JOB => V_JOB,
		WHAT => 'BEGIN MY_PKG.MY_EXEC_PROC; END;',
		NEXT_DATE => SYSDATE);
  commit;
  dbms_output.put_line('Created MY_PKG.MY_EXEC_PROC  job: '||v_job);
END;
/ 
Este script tem o seguinte problema: se executarmos o script outra vez o resultado vai ser a criação de outro job igual ao primeiro. Este foi alias a situação com que me deparei de início: a base de dados tinha dezenas de jobs a realizar a mesma tarefa!
Posto o problema de apenas o campo job (do tipo número) identificar univocamente o job, utilizei o campo what para o identificar. Criei o seguinte script de deploy:
DECLARE
  V_JOB NUMBER;
  V_WHAT VARCHAR2(100) := 'BEGIN MY_PKG.MY_EXEC_PROC; END;';
  V_NEXT_DATE DATE := SYSDATE;
BEGIN
  dbms_output.put_line('Deleting all MY_PKG.MY_EXEC_PROC jobs:');
	FOR jobs_to_delete IN (
    SELECT  job
	    FROM user_jobs 
	    WHERE what like V_WHAT
   ) LOOP
     dbms_output.put_line('...removing MY_PKG.MY_EXEC_PROC job ' || jobs_to_delete.job);
     dbms_job.remove(jobs_to_delete.job);
  END LOOP;
  dbms_output.put_line('Deleted all MY_PKG.MY_EXEC_PROC jobs.');
  commit;
  
  DBMS_JOB.SUBMIT(V_JOB, V_WHAT, V_NEXT_DATE);
  commit;
  dbms_output.put_line('Created MY_PKG.MY_EXEC_PROC job: '||v_job);
END;
/ 
Reparar no loop para resolver o caso de fazerem deploy do mesmo job.
Este script não resolve outro problema: se numa fase de desenvolvimento alterarmos o what do job não iremos remover os jobs antigos – claro que esta situação tem pouco impacto com algum controlo regular sobre o que existe na base de dados.
Este script poderia ser isolado num procedimento com a assinatura
DEPLOY_JOB( job OUT BINARY_INTEGER, what IN VARCHAR2, next_date IN DATE DEFAULT sysdate, interval IN VARCHAR2 DEFAULT 'null', job_name IN VARCHAR2); -- 'job_name' serve apenas para dbms_output
que não é mais do que estender as funcionalidades do DBMS_JOB.SUBMIT.
Oracle 10g: o DBMS_SCHEDULER
Mas eis que a 10g apresenta uma solução muito mais completa: o package DBMS_SCHEDULER.
Eis o novo script de deploy proposto
DECLARE
  V_JOB_NAME VARCHAR2(100) := 'MY_PKG_MY_EXEC_PROC';
BEGIN
  DBMS_SCHEDULER.DROP_JOB( 
    job_name          =>  V_JOB_NAME );
  DBMS_SCHEDULER.CREATE_JOB(
		job_name          =>  V_JOB_NAME,
		job_type          =>  'PLSQL_BLOCK',
		job_action        =>  'BEGIN MY_PKG.MY_EXEC_PROC; END;');
		start_date        =>  SYSDATE );
END;
/ 
job_name
This attribute specifies the name of the job and uniquely identifies the job.
The name has to be unique in the SQL namespace. For example, a job cannot have the same name as a table in a schema.
If job_name is not specified, an error is generated. If you want to have a name generated by the Scheduler, you can use the GENERATE_JOB_NAME procedure to generate a name and then use the output in the CREATE_JOB procedure. The GENERATE_JOB_NAME procedure call generates a number from a sequence, which is the job name. You can prefix the number with a string. The job name will then be the string with the number from the sequence appended to it. 
Além do job ter um identificador descritivo, não é apenas único na lista de jobs mas também em todo o schema.
E com o DBMS_SCHEDULER.GENERATE_JOB_NAME nem precisariamos de nos preocupar com o nome do job, similar ao DBMS_JOBS.
E óptimo disponibilizar a geração de valores para job_name com prefixo, muito útil em aplicações que geram internamente jobs e que teriam de implementar esta geração do nome.
Nota importante: ao contrário do DBMS_JOB.SUBMIT, o DBMS_SCHEDULER.CREATE_JOB faz commit, tentando ser similar a um statement DDL.
Leituras
- [1] Oracle Database Administrator’s Guide 10g Release 1 (http://www.oracle.com)
 - [2] PLSQL Packages and Types Reference 10g Release 1 (http://www.oracle.com)
 
Oracle
 Ainda bem que tu é que fazes isso e não eu.
Concordo.
Existem coisas q ninguem quer fazer.
Voces ja perceberam que nao tem nenhum email de voces no site inteiro? Fica dificil de entrar em contato…
brgds,
Papick G. Taboada
Tens toda a razão, vou tentar resolver isso e meter o mail na parte do “Sobre Nós”
Correndo a base de dados da Oracle Java, que tal usares o quartz por la – http://www.opensymphony.com/quartz/
Tens toda a razão, vou tentar resolver isso e meter o mail na parte do “Sobre Nós”