Bulk Collection forall

Dúvidas, dicas e truques de PL/SQL. Aqui também vão assuntos relacionados a pacotes, triggers, funções, Java-Stored Procedures, etc
Responder
bernoulthy
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 3
Registrado em: Sáb, 02 Out 2010 5:11 pm
Localização: SP

Ola pessoal estou com uma dúvida referente a Bulk collect com for all
segue um pequeno exemplo:

Selecionar tudo

create or replace procedure test is

  cursor c1 is select * from cliente;
  type c_collect is table of cliente2%rowtype;
  colecao c_collect;

begin
  open c1;
  loop
    fetch c1 bulk collect into colecao;
    exit when colecao.count = 0;
    forall i in 1..colecao.count
    insert into cliente2  values colecao(i);
  end loop;
end;
dessa maneira funciona perfeitamente, o problema é quando tento especificar apenas alguns campos no select do cursor ao invés de fazer um select com *, por exemplo:

Selecionar tudo

create or replace procedure test is

  cursor c1 is select id, nome, sobrenome  from cliente;
  type c_collect is table of cliente2%rowtype;
  colecao c_collect;

begin
  open c1;
  loop
    fetch c1 bulk collect into colecao;
    exit when colecao.count = 0;
    forall i in 1..colecao.count
    insert into cliente2  values colecao(i);
  end loop;
end;
aparece um erro dizendo que número incorreto de valores na lista até ai eu entendi, porque a minha coleção está pegando a estrutura de uma tabela.
ai então eu faço a coleção pegar a estrutura do cursor:

Selecionar tudo

cursor c1 is select id, nome, sobrenome  from cliente;
type c_collect is table of c1%rowtype;
ai o erro cai para a linha do insert, dizendo que não valores suficientes

Selecionar tudo

forall i in 1..colecao.count
insert into cliente2  values colecao(i); <-- erro nessa linha
pois minha intenção é utilizar o forall para fazer o insert de uma massa de dados, porem não será em todos os campos da tabela

será se alguém pode me ajudar;
gfkauer
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 389
Registrado em: Ter, 27 Jul 2010 1:34 pm
Localização: Sapiranga - RS
Contato:
Quem falou que programar era fácil??

Quanto mais dificil for a implementação mais valorizado seu trabalho será!

Acessem: www.gfkauer.com.br

para usar forall insert você precisa "ter" todas as colunas no select, mesmo que sejam com um valor Null ou 0.

O comando forall insert não permite especificar quais colunas vai inserir.
thiago_r_f
Rank: Programador Pleno
Rank: Programador Pleno
Mensagens: 43
Registrado em: Qui, 17 Abr 2008 4:02 pm
Localização: Rio de Janeiro - RJ
O Backup é meu pastor e nada me faltará!
Thiago Rodrigues de Farias

Fiz um teste rápido aqui e funcionou. O erro que tomei foi por conta do EXIT WHEN c1.COUNT = 0; que deixei cometado e utilizei outra maneira de sair do laço (e não deu pra investigar direitinho o porquê do erro).
Espero que ajude.
Abs

Selecionar tudo

CREATE TABLE teste AS
 SELECT table_name, tablespace_name
 FROM user_tables
 WHERE 1=2;

DECLARE
 CURSOR c1 IS
 SELECT table_name, tablespace_name
 FROM user_tables;

 TYPE fetch_array IS TABLE OF c1%ROWTYPE;
 s_array fetch_array;
BEGIN
  OPEN c1;
  LOOP
    FETCH c1 BULK COLLECT INTO s_array LIMIT 1000;

    --EXIT WHEN c1.COUNT = 0;

    FORALL i IN 1..s_array.COUNT
    INSERT INTO teste VALUES s_array(i);

    EXIT WHEN c1%NOTFOUND;

  END LOOP;
  CLOSE c1;
  COMMIT;
END;
thiago_r_f
Rank: Programador Pleno
Rank: Programador Pleno
Mensagens: 43
Registrado em: Qui, 17 Abr 2008 4:02 pm
Localização: Rio de Janeiro - RJ
O Backup é meu pastor e nada me faltará!
Thiago Rodrigues de Farias

Opa! Só pra colocar a alternativa que não tinha dado certo da outra vez e que agora funcionou (é a correria!).

Selecionar tudo

DECLARE
 CURSOR c1 IS
 SELECT table_name, tablespace_name
 FROM user_tables;
 TYPE fetch_array IS TABLE OF c1%ROWTYPE;
 s_array fetch_array;
BEGIN
  OPEN c1;
  LOOP
    FETCH c1 BULK COLLECT INTO s_array LIMIT 1000;
    EXIT WHEN s_array.COUNT = 0;
    FORALL i IN 1..s_array.COUNT
    INSERT INTO teste VALUES s_array(i);
  END LOOP;
  CLOSE c1;
  COMMIT;
END;
Responder
  • Informação