Boa tarde !
Preciso alimentar uma tabela com dados que leio através de um SQL. Tentei usar insert normal mas ficou muito lento !
Verifiquei na internet e vi que o pessoal usa BULK COLLECTION mas não consegui montar algo funcional. Você pode me ajudar com alguma dica ?
Toledo
Toledo, como conversado anteriormente, irei demonstrar como podemos resolver esse seu problema utilizando FORALL.O objetivo desse post não é discutir sobre sua performance, e sim sobre como o implementar em seu código.
Primeiramente, vamos criar as nossas tabelas para o nosso teste e inserir alguns dados:
CREATE TABLE teste ( codigo NUMBER, descricao VARCHAR2(2000) ) / INSERT INTO teste (codigo,descricao) VALUES (1,'DESCRICAO 1'); INSERT INTO teste (codigo,descricao) VALUES (2,'DESCRICAO 2'); INSERT INTO teste (codigo,descricao) VALUES (3,'DESCRICAO 3'); INSERT INTO teste (codigo,descricao) VALUES (4,'DESCRICAO 4'); INSERT INTO teste (codigo,descricao) VALUES (5,'DESCRICAO 5'); INSERT INTO teste (codigo,descricao) VALUES (6,'DESCRICAO 6'); INSERT INTO teste (codigo,descricao) VALUES (7,'DESCRICAO 7'); INSERT INTO teste (codigo,descricao) VALUES (8,'DESCRICAO 8'); INSERT INTO teste (codigo,descricao) VALUES (9,'DESCRICAO 9'); INSERT INTO teste (codigo,descricao) VALUES (10,'DESCRICAO 10'); INSERT INTO teste (codigo,descricao) VALUES (1,'DESCRICAO 1'); INSERT INTO teste (codigo,descricao) VALUES (2,'DESCRICAO 2'); INSERT INTO teste (codigo,descricao) VALUES (3,'DESCRICAO 3'); INSERT INTO teste (codigo,descricao) VALUES (4,'DESCRICAO 4'); INSERT INTO teste (codigo,descricao) VALUES (5,'DESCRICAO 5'); INSERT INTO teste (codigo,descricao) VALUES (6,'DESCRICAO 6'); INSERT INTO teste (codigo,descricao) VALUES (7,'DESCRICAO 7'); INSERT INTO teste (codigo,descricao) VALUES (8,'DESCRICAO 8'); INSERT INTO teste (codigo,descricao) VALUES (9,'DESCRICAO 9'); INSERT INTO teste (codigo,descricao) VALUES (10,'DESCRICAO 10'); CREATE TABLE teste2 ( codigo NUMBER, descricao VARCHAR2(2000) ) /
Pronto, agora vamos ao nosso código:
DECLARE -- Variable TYPE v_tabData IS TABLE OF teste%ROWTYPE; v_tabBulk v_tabData; x NUMBER := 0 CURSOR c1 IS SELECT a.codigo ,a.descricao FROM teste a; BEGIN -- Trunca a tabela DBMS_OUTPUT.put_line('Truncando a tabela...'); DBMS_UTILITY.exec_ddl_statement('TRUNCATE TABLE teste2'); OPEN c1; LOOP DBMS_OUTPUT.put_line('Iniciando leitura...'); -- Fetch Collection FETCH c1 BULK COLLECT INTO v_tabBulk; DBMS_OUTPUT.put_line('Registro(s) a serem processados: ' || v_tabBulk.COUNT ); -- Verifica se há registros IF v_tabBulk.COUNT > 0 THEN FORALL x IN 1..v_tabBulk.COUNT INSERT INTO teste2 VALUES v_tabBulk(x); DBMS_OUTPUT.put_line('Registros processados...'); END IF; EXIT WHEN c1%NOTFOUND; COMMIT; END LOOP; -- Não esqueça de fechar o seu cursor :) CLOSE c1; DBMS_OUTPUT.put_line('Fim do processo...'); EXCEPTION WHEN others THEN DBMS_OUTPUT.put_line('[ ERRO ] ' || DBMS_UTILITY.format_error_stack); IF SQL%ISOPEN THEN -- Não esqueça de fechar o seu cursor :) CLOSE c1; END IF; END;
Como a estrutura da tabela é idêntica ao do resultado do SELECT, pude utilizar o ROWTYPE da tabela como record do meu TYPE do tipo TABLE. O que facilita em muito o trabalho. Observe que estou lendo todos os dados da TABELA 1 e salvando na TABELA2.
Pronto Toledo, agora é só adaptar a suas necessidades. Espero que seja de grande ajuda a você e ao pessoal que acompanha o blog.
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).
Olá Sérgio, boa tarde!
Muito boa dica, parabéns!
Preciso de um help. No caso do cursor ser referente a tabelas relacionadas como fazer? É a mesma lógica?
Olá Notria !
Sim, a lógica é a mesma. Só se atente ao fato de que a estrutura do TYPE deve ser compatível com a estrutura da tabela na qual os dados serão inseridos.