Pular para o conteúdo
  • Este tópico contém 1 resposta, 2 vozes e foi atualizado pela última vez 7 anos, 12 meses atrás por Avatar photoJosé Laurindo Chiappa.
Visualizando 2 posts - 1 até 2 (de 2 do total)
  • Autor
    Posts
  • #108515
    Avatar de Douglas Amaral FernandesDouglas Amaral Fernandes
    Participante

      Hoje eu tenho uma procedure que pega um cursor e faz um loop e faz insert,update,delete
      uma a uma linha

      ..

      declare
      CURSOR C_EXEC IS
      SELECT /*+ FULL(DCREP_SINCRO_LEITURA) */ NR_ITEM_SINCR,
      CODFILIAL,
      TP_ATUALIZACAO,
      NOM_TABELA,
      INSTRUCAO,
      NOME_ARQUIVO,
      NR_AUXILIAR,
      NR_GERADO,
      CHAVE_COLUNA,
      ROWID
      FROM DCREP_SINCRO_LEITURA
      WHERE CODFILIAL = 2 + UID * 0
      AND TP_ATUALIZACAO = 2
      ORDER BY NR_ITEM_SINCR, NR_AUXILIAR;

      /* SELECT NR_ITEM_SINCR,
      CODFILIAL,
      TP_ATUALIZACAO,
      NOM_TABELA,
      INSTRUCAO,
      NOME_ARQUIVO,
      NR_AUXILIAR,
      NR_GERADO,
      CHAVE_COLUNA,
      ROWID
      FROM DCREP_SINCRO_LEITURA
      order by NR_ITEM_SINCR, NR_AUXILIAR;*/

      vNAO_SINCRONIZA NUMBER(10) := 0;
      vCOUNT NUMBER(10) := 0;

      BEGIN

      FOR C1 IN C_EXEC LOOP
      /*
      SELECT COUNT(*)
      INTO vNAO_SINCRONIZA
      FROM DCREP_SINCRO_MATRIZ
      WHERE ENVIADO = ‘N’;*/

      IF vNAO_SINCRONIZA > 0 THEN
      EXIT;
      END IF;
      vCOUNT := vCOUNT + 1;

      If C1.TP_ATUALIZACAO = 1 Then
      PCG_SINCRO_MATRIZ.INCLUSAO(C1.NR_ITEM_SINCR,
      C1.CODFILIAL,
      C1.TP_ATUALIZACAO,
      C1.NOM_TABELA,
      C1.INSTRUCAO,
      C1.NOME_ARQUIVO,
      C1.NR_AUXILIAR,
      C1.NR_GERADO,
      C1.CHAVE_COLUNA);

      Elsif C1.TP_ATUALIZACAO = 2 Then
      PCG_SINCRO_MATRIZ.ALTERACAO(C1.NR_ITEM_SINCR,
      C1.CODFILIAL,
      C1.TP_ATUALIZACAO,
      C1.NOM_TABELA,
      C1.INSTRUCAO,
      C1.NOME_ARQUIVO,
      C1.NR_AUXILIAR,
      C1.NR_GERADO,
      C1.CHAVE_COLUNA);
      Elsif C1.TP_ATUALIZACAO = 3 Then
      PCG_SINCRO_MATRIZ.EXCLUSAO(C1.NR_ITEM_SINCR,
      C1.CODFILIAL,
      C1.TP_ATUALIZACAO,
      C1.NOM_TABELA,
      C1.INSTRUCAO,
      C1.NOME_ARQUIVO,
      C1.NR_AUXILIAR,
      C1.NR_GERADO,
      C1.CHAVE_COLUNA);
      End if;

      DELETE /*+ APPEND */ DCREP_SINCRO_LEITURA WHERE ROWID = C1.ROWID;

      IF vCOUNT >= 50 THEN
      COMMIT;
      END IF;

      END LOOP;
      commit;

      END;

      Tem como fazer essa inserção de uma so vez.. ao invés de linha a linha

      #108516
      Avatar photoJosé Laurindo Chiappa
      Moderador

        Bom, antes de te responder algumas obs :

        a. DELETE /*+ APPEND */ é ABSURDO, NÂO SERVE PARA NADA a não ser desperdiçar espaço no seu código, NÂO está fazendo NADA DE NADA acontecer : pode consultar a Documentação Oracle que APPEND só funciona para INSERT, e em casos muito específicos, com vários pré-requisitos

        b. COMMIT a cada poucas linhas só serve para causar MAIS DEMORA no processamento, gastar recursos e dar a chance de quebrar a integridade de dados – se vc quer máxima performance e Integridade a nível de transação, mantenha UNDO e REDO em tamanhos adequadois e COMMIT só no final : https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:4951966319022 é a melhor ref

        c. NÂO TEM como a gente analisar em detalhes um código com mais do que um punhadinho mínimo de linhas (até porque Não éuma Consultoria aqui mas um Fórum, então Ninguém tem tempo nem condição de fazer nenhuma Análise Profunda, nem é o Objetivo) mas ao que parece, a primeira coisa que está forçando o RDBMS a processar linha-por-linha é esse cursor FOR aí – quando se fala em performance, SQL direto, sem Cursor, é Incinparavelmente mais rápido…
        E adicionalmente, pelo que pude perceber vc quer processar um resultset de uma query, e para cada linha se uma condição for verdadeira vc faz INSERT, se outra for verdadeira vc faz UPDATE, e no final deleta a linha processada : o comando SQL apropriado que faz tudo isso de uma tacada só (*** EVITANDO ** processamento linha-a-linha!!) se chama MERGE – consulte a documentação Oracle (e as boas refs, como https://oracle-base.com/articles/9i/merge-statement e seus links, https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:6618304976523 e http://www.oratable.com/oracle-merge-command-for-upsert/. por exemplo) para aprender como se usa ele e tente adaptá-lo pras suas necessidades….

        ===>>> CASO ** realmente **, por alguma lógica complexa ou por qquer necessidade específica e restrita que vc tenha, seja MESMO, de verdade, completamentamente Inviável usar SQL sem loop e/ou MERGE, outra OPção seria vc trabalhar com ARRAYs, lendo e mandando pro banco um ARRAY com múltiplos registros : olha na Documentação e googla por BULK COLLECT e ARRAY PROCESSING…..
        Via de regra isso é INFERIOR ao uso de SQL direto, sem loop/cursor, mas deve ser superior ao processamento row-by-row/uma linha por ves, que não sem motivo é chamado de SLOW BY SLOW em alguns círculos….

        []s

        Chiappa

      Visualizando 2 posts - 1 até 2 (de 2 do total)
      • Você deve fazer login para responder a este tópico.
      plugins premium WordPress