Pular para o conteúdo

Inserindo dados em uma tabela utilizando FORALL

Inserindo dados em uma tabela utilizando FORALL

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

Quão útil foi este post ?

Clique em uma estrela para classificar o post

nota média 4.7 / 5. Contagem de votos: 30

Sem votos ! Seja o primeiro a classificar !

4 comentários em “Inserindo dados em uma tabela utilizando FORALL”

  1. Avatar de Notria

    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?

  2. Avatar de Luiz

    Olá. Por favor, usando FORALL, preciso executar dois updates, em tabelas diferentes, dentro do mesmo loop. Como ficaria a sintaxe do FORALL? eu preciso colocar um FORALL para cada update? Estou fazendo assim:
    loop
    forall i in first .. last
    execute immediate
    update 1

    forall i in firt .. last
    execute immediate
    update 2

    commit;
    end loop;

    se puder tirar essa dúvida, agradeço. obrigado.

Deixe um comentário para Notria Cancelar resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

plugins premium WordPress