Olá pessoal !
Neste exemplo irei demonstrar como se passa uma collection como parâmetro de um job. Para isso, iremos utilizar o nosso velho amigo ANYDATA, que foi alvo de outros dois artigos escritos por mim e que podem ser encontrados aqui no GPO.
Primeiro iremos criar uma tabela para armazenar os dados processados:
CREATE TABLE tJobTeste ( DESCRIPTION VARCHAR2(2000) ) / CREATE PUBLIC SYNONYM tJobTeste FOR tJobTeste /
Agora criaremos os types que armazenarão a nossa collection:
CREATE OR REPLACE TYPE rowPipe AS OBJECT (description VARCHAR2(2000)) / CREATE OR REPLACE TYPE tabPipe AS TABLE OF rowPipe /
Agora vamos criar a SPEC da Package:
CREATE OR REPLACE PACKAGE jobTest AS -- Cria o Job PROCEDURE createJob ( p_pipe tabPipe ); -- Processa os Dados PROCEDURE insertData ( p_pipe tabPipe ); END jobTest;
E finalmente, a BODY !
CREATE OR REPLACE PACKAGE BODY jobTest AS -- -- Cria o Job e trata a Collection -- PROCEDURE createJob ( p_pipe tabPipe ) AS PRAGMA AUTONOMOUS_TRANSACTION; vJobName VARCHAR2(2000) := 'COLJOBTEST'; BEGIN -- Cria o JOB DBMS_SCHEDULER.create_job ( job_name => vJobName ,job_type => 'STORED_PROCEDURE' ,job_action => 'JOBTEST.insertData' ,number_of_arguments => 1 ,start_date => SYSTIMESTAMP ,job_class => '' ,enabled => FALSE ,auto_drop => TRUE -- O Job se auto destruirá ,comments => 'Job Creation Test' ); -- Seta o parâmetro como ANYDATA DBMS_SCHEDULER.set_job_anydata_value ( job_name => vJobName ,argument_position => 1 ,argument_value => SYS.ANYDATA.ConvertCollection(p_pipe) ); -- Habilita o Job DBMS_SCHEDULER.enable ( name => vJobName ); END createJob; -- -- Processa o Collection -- PROCEDURE insertData ( p_pipe tabPipe ) IS BEGIN FOR x IN p_pipe.FIRST..p_pipe.LAST LOOP BEGIN INSERT INTO tJobTeste VALUES (p_pipe(x).description); EXCEPTION WHEN OTHERS THEN INSERT INTO tJobTeste VALUES (DBMS_UTILITY.format_error_stack); END; COMMIT; END LOOP; END insertData; BEGIN NULL; END jobTest;
O truque para passar a collection como parâmetro, é criar o JOB com o parâmetro ENABLE como FALSE, e utilizar DBMS_SCHEDULER.set_job_anydata_value para setá-lo. Depois, basta utilizar o DBMS_SCHEDULER.enable para que ele comece a execução de imediato.
Agora vamos testar a nossa PACKAGE:
DECLARE tPipe tabPipe := tabPipe(); x NUMBER := 0; BEGIN -- Preenche a collection FOR x IN 1..5 LOOP tPipe.EXTEND; tPipe(x) := rowPipe('TESTE -' || x); END LOOP; -- Executa a rotina jobTest.createJob(tPipe); END; PL/SQL procedure successfully completed.
Vamos verificar o status de nosso JOB:
SELECT * FROM dba_scheduler_job_run_details Where job_name LIKE 'COLJOB%' ORDER BY actual_start_date DESC /
O JOB executou com sucesso ! Agora vamos ver o resultado do processamento:
SELECT * FROM tJobTeste /
O resultado foi o esperado, e os dados foram processados e inseridos na tabela ! 🙂
O ANYDATA nos dá uma incrível flexibilidade para transportar coleções, como observaram nos últimos artigos escritos, é possível criar soluções inteligentes com boa performance se utilizando desse expediente.
Esse é o último artigo da série ANYDATA. Caso tenham alguma dúvida sobre sua utilização ou quais contextos utilizar, é só entrar em contato !
Um grande abraço

Formado em Gestão em Tecnologia da Informação, com sólidos conhecimentos em SQL, PL/SQL, Oracle Forms, Reports e E-Business Suite (AP,AR e GL).
Foi durante 3 anos gerente de tecnologia de grande empresa do setor de saúde, e atualmente atua como Analista de Sistema Sênior na Scania Latin America e também como Diretor-fundador do GPO (Grupo de Profissionais Oracle).