BULK COLLECT e 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
cleberzumba
Rank: DBA Júnior
Rank: DBA Júnior
Mensagens: 223
Registrado em: Qui, 14 Dez 2006 10:45 am
Localização: Brasília-DF
Cleber Zumba de Souza

Pessoal, está me dando erro sinistro, mas o que está errado?

Selecionar tudo

declare --(a procedure recebe parametros)     
     
    
  	type t_lancamento is table of TBEA_CARGA_LANCTO_CONTABIL_TMP%rowtype
	index by binary_integer;

    v_lancamento  t_lancamento;


BEGIN

    select *
    bulk collect into v_lancamento
    from  TBEA_CARGA_LANCTO_CONTABIL_TMP
    where  CLCO_NUM_ARQ = p_num_arq;
            

begin
                forall v_count in v_lancamento.first .. v_lancamento.last --save exceptions
      
                
                -- insert na tabela TBEA_CARGA_LANCTO_CONTABIL.
                insert into TBEA_CARGA_LANCTO_CONTABIL /*+ Append */ (CLCO_NUM_CAP_LOTE),
                                                        CLCO_ITEM_LOTE,
                                                        CLCO_NUM_LAN_SAP,
                                                        CLCO_ANOMES_MOVTO,
                                                        CLCO_ORIGEM,
                                                        CLCO_COD_EMPRESA,
                                                        CLCO_COD_FILIAL,
                                                        CLCO_DAT_DOCTO,
                                                        CLCO_TIP_DOCTO,
                                                        CLCO_DAT_LANCTO,
                                                        CLCO_TEX_CAB,
                                                        CLCO_IND_TIP_LANCTO,
                                                        CLCO_IND_ANA_SINT,
                                                        CLCO_REF_LANC)
                values (v_lancamento.CLCO_NUM_CAP_LOTE (v_count),
                        v_lancamento.CLCO_ITEM_LOTE(v_count),
                        v_lancamento.CLCO_NUM_LAN_SAP(v_count),
                        v_lancamento.CLCO_ANOMES_MOVTO(v_count),
                        v_lancamento.CLCO_ORIGEM(v_count),
                        v_lancamento.CLCO_COD_EMPRESA(v_count),
                        v_lancamento.CLCO_COD_FILIAL(v_count),
                        v_lancamento.CLCO_DAT_DOCTO(v_count),
                        v_lancamento.CLCO_TIP_DOCTO(v_count),
                        v_lancamento.CLCO_DAT_LANCTO(v_count),
                        v_lancamento.CLCO_TEX_CAB(v_count),
                        v_lancamento.CLCO_IND_TIP_LANCTO(v_count),
                        v_lancamento.CLCO_IND_ANA_SINT(v_count),
                        v_lancamento.CLCO_REF_LANC(v_count));

exception
     when others then
             rollback;

END; -- Procedure
joaogarcia
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 91
Registrado em: Ter, 20 Mar 2007 7:19 pm
Localização: Campinas - SP
Contato:
Cordialmente,
João C. Garcia

Cara... Achei vários erros no seu código. Dá uma olhada nas modificações que fiz. Talvez funcione.

Selecionar tudo

DECLARE     
  --  
  cursor c_processos is
    select * from  TBEA_CARGA_LANCTO_CONTABIL_TMP where  CLCO_NUM_ARQ = p_num_arq;   
  --
  type t_lancamento is table of TBEA_CARGA_LANCTO_CONTABIL_TMP%rowtype index by pls_integer;
  v_lancamento  t_lancamento;
  --
BEGIN
  --
  OPEN c_processos;
  --
  LOOP
  FETCH c_processos BULK COLLECT INTO v_lancamento LIMIT 500;
    --  
    FORALL indx IN 1.. v_lancamento.COUNT 
      insert into TBEA_CARGA_LANCTO_CONTABIL (CLCO_NUM_CAP_LOTE,
                                              CLCO_ITEM_LOTE,
                                              CLCO_NUM_LAN_SAP,
                                              CLCO_ANOMES_MOVTO,
                                              CLCO_ORIGEM,
                                              CLCO_COD_EMPRESA,
                                              CLCO_COD_FILIAL,
                                              CLCO_DAT_DOCTO,
                                              CLCO_TIP_DOCTO,
                                              CLCO_DAT_LANCTO,
                                              CLCO_TEX_CAB,
                                              CLCO_IND_TIP_LANCTO,
                                              CLCO_IND_ANA_SINT,
                                              CLCO_REF_LANC)
      values (v_lancamento(indx).CLCO_NUM_CAP_LOTE,
              v_lancamento(indx).CLCO_ITEM_LOTE,
              v_lancamento(indx).CLCO_NUM_LAN_SAP,
              v_lancamento(indx).CLCO_ANOMES_MOVTO,
              v_lancamento(indx).CLCO_ORIGEM,
              v_lancamento(indx).CLCO_COD_EMPRESA,
              v_lancamento(indx).CLCO_COD_FILIAL,
              v_lancamento(indx).CLCO_DAT_DOCTO,
              v_lancamento(indx).CLCO_TIP_DOCTO,
              v_lancamento(indx).CLCO_DAT_LANCTO,
              v_lancamento(indx).CLCO_TEX_CAB,
              v_lancamento(indx).CLCO_IND_TIP_LANCTO,
              v_lancamento(indx).CLCO_IND_ANA_SINT,
              v_lancamento(indx).CLCO_REF_LANC);
    --
    EXIT WHEN c_processos%NOTFOUND;   
    -- 
  END LOOP;
  --
  CLOSE c_processos;
  --
EXCEPTION
  WHEN OTHERS THEN
    ROLLBACK;
END;
cleberzumba
Rank: DBA Júnior
Rank: DBA Júnior
Mensagens: 223
Registrado em: Qui, 14 Dez 2006 10:45 am
Localização: Brasília-DF
Cleber Zumba de Souza

muito bom.

no exception, ele tem q inserir em uma tabela, aí terei que fazer um outro FETCH ?

Selecionar tudo

FETCH c_ BULK COLLECT INTO
joaogarcia
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 91
Registrado em: Ter, 20 Mar 2007 7:19 pm
Localização: Campinas - SP
Contato:
Cordialmente,
João C. Garcia

Mesmo esquema...
Outra coisa, se der erro no seu insert, tenta isso:

Selecionar tudo

insert into TBEA_CARGA_LANCTO_CONTABIL values v_lancamento(indx);
T+
cleberzumba
Rank: DBA Júnior
Rank: DBA Júnior
Mensagens: 223
Registrado em: Qui, 14 Dez 2006 10:45 am
Localização: Brasília-DF
Cleber Zumba de Souza

mas se eu fizer um novo fetch no exception, eu não vou conseguir pegar o registro q deu erro.
joaogarcia
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 91
Registrado em: Ter, 20 Mar 2007 7:19 pm
Localização: Campinas - SP
Contato:
Cordialmente,
João C. Garcia

Entendi...
Então, usa For Loop ao invés de Forall...
Ficaria assim:

Selecionar tudo

FOR indx IN 1.. v_lancamento.COUNT LOOP
      BEGIN
        insert into TBEA_CARGA_LANCTO_CONTABIL values v_lancamento(indx); ;      
      EXCEPTION
      WHEN OTHERS THEN
          /* INSERE EM OUTRA TABELA...*/
      END;
    END LOOP;
cleberzumba
Rank: DBA Júnior
Rank: DBA Júnior
Mensagens: 223
Registrado em: Qui, 14 Dez 2006 10:45 am
Localização: Brasília-DF
Cleber Zumba de Souza

beleza, deu certo meu camarada. mas seguinte, eu estou trabalhando com uma quantidade de registro muito grande, algo em torno de 20 milhões, 60 milhões de registros e isso não implicaria na performance?
joaogarcia
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 91
Registrado em: Ter, 20 Mar 2007 7:19 pm
Localização: Campinas - SP
Contato:
Cordialmente,
João C. Garcia

Então....
O Bulk Collect com Limit é o que oferece a melhor performance.
Quanto a usar o For Loop, não vejo outra forma já que você vai tratar os registros um a um.
Outra coisa, este Loop aí vai ser por "Lotes" conforme o valor do Limit.

Se alguém tiver alguma sugestão para o colega, fique à vontade...

T+
cleberzumba
Rank: DBA Júnior
Rank: DBA Júnior
Mensagens: 223
Registrado em: Qui, 14 Dez 2006 10:45 am
Localização: Brasília-DF
Cleber Zumba de Souza

beleza, valeu...também não vejo outra solução!
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 12 visitantes