- Este tópico contém 1 resposta, 2 vozes e foi atualizado pela última vez 7 anos, 12 meses atrás por José Laurindo Chiappa.
-
AutorPosts
-
23 de novembro de 2016 às 10:59 pm #108515Douglas Amaral FernandesParticipante
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
24 de novembro de 2016 às 4:32 am #108516José Laurindo ChiappaModeradorBom, 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
-
AutorPosts
- Você deve fazer login para responder a este tópico.