Procedure não comita todos os valores

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
lucasesr
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 10
Registrado em: Ter, 06 Nov 2012 1:56 pm

Boa noite galera.

Estou com o seguinte problema.
Criei uma procedure que lê alguns dados do cursor, joga esses dados para uma Type. Que atendendo à algumas regras faz o update.
O problema vem agora. Vamos dizer que o cursor retorne 1000 Registros, mas depois que eu executo a procedure apenas 200 foram alterados. Ficando 800 registros sem atualizar. Se eu rodar novamente, mas alguns registros são atualizados e outros não...

Segue abaixo a versão, ferramenta e o código.

Versão do SGBD: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
Ferramenta: Oracle SQL Developer (3.2.20.09)

Selecionar tudo

create or replace 
PACKAGE BODY PACK_COMPARA_SOLIC IS
  ------------------------------------------------------------------------------------
  PROCEDURE PROC_QRY_COMPARA_SOLIC(P_TYPE         IN OUT NOCOPY TYP_TAB_EV_COMPARA,
																	 P_CD_RETORNO   OUT NUMBER,
																	 P_DS_MENSAGEM  OUT VARCHAR2) IS
  ------------------------------------------------------------------------------------
    V_CONT NUMBER(10) := 0;
  
    CURSOR CUR_TYPE IS
      SELECT
        EVS1.ID_ACESSO,
        EVS1.COD_SOLIC,
        REPLACE(REPLACE(TO_CHAR(EVS2.IP_LAN_01_F), CHR(10), ''), CHR(13), '') AS IP_LAN_01_F_A,
        REPLACE(REPLACE(TO_CHAR(EVS1.IP_LAN_01_I), CHR(10), ''), CHR(13), '') AS IP_LAN_01_I,
        REPLACE(REPLACE(TO_CHAR(EVS1.IP_LAN_01_F), CHR(10), ''), CHR(13), '') AS IP_LAN_01_F,
        EVS1.IP_LAN_01_A,
        CASE WHEN EVS1.IP_LAN_01_A = 'SIM' THEN
          CASE WHEN NVL(TO_CHAR(EVS2.IP_LAN_01_F), 'NULL') = NVL(TO_CHAR(EVS1.IP_LAN_01_I), 'NULL') THEN 'OK' ELSE 'ERRO' END 
        ELSE -- NÃO É ALTERADO
          CASE WHEN NVL(TO_CHAR(EVS2.IP_LAN_01_F), 'NULL') = NVL(TO_CHAR(EVS1.IP_LAN_01_F), 'NULL') THEN 'OK' ELSE 'ERRO' END 
        END AS IP_LAN_01_C
      FROM
        EV_COMPARA_SOLIC_BKB EVS1

        LEFT JOIN EV_CONCORRENTE_SOLIC EVCS1 ON EVS1.COD_SOLIC = EVCS1.COD_SOLIC_ATUAL

        JOIN EV_ORDEM_SOLIC EVO1 ON EVS1.COD_SOLIC = EVO1.COD_SOLIC

        JOIN EV_COMPARA_SOLIC_BKB EVS2 ON EVO1.COD_SOLIC_ANT = EVS2.COD_SOLIC

        JOIN (SELECT EVO1.ID_ACESSO, MIN(EVO1.COD_ORDEM) COD_ORDEM FROM EV_ORDEM_SOLIC EVO1 WHERE EVO1.COD_SOLIC_TIPO = 600 GROUP BY EVO1.ID_ACESSO) T1 ON EVS1.ID_ACESSO = T1.ID_ACESSO
        WHERE (EVS1.IP_LAN_01_A = 'SIM' AND NVL(TO_CHAR(EVS2.IP_LAN_01_F), 'NULL') <> NVL(TO_CHAR(EVS1.IP_LAN_01_I), 'NULL'))
           OR (EVS1.IP_LAN_01_A = 'NÃO' AND NVL(TO_CHAR(EVS2.IP_LAN_01_F), 'NULL') <> NVL(TO_CHAR(EVS1.IP_LAN_01_F), 'NULL'))
      ORDER BY
        EVO1.COD_ORDEM ASC;
				
  BEGIN
    DBMS_OUTPUT.DISABLE();
    
    V_CONT := 0;
    
    FOR X IN CUR_TYPE LOOP
      V_CONT := V_CONT + 1;
    
      P_TYPE(V_CONT).ID_ACESSO 			:= X.ID_ACESSO;
      P_TYPE(V_CONT).COD_SOLIC 			:= X.COD_SOLIC;
      P_TYPE(V_CONT).IP_LAN_01_F_A	:= X.IP_LAN_01_F_A;
      P_TYPE(V_CONT).IP_LAN_01_I    := X.IP_LAN_01_I;
      P_TYPE(V_CONT).IP_LAN_01_F    := X.IP_LAN_01_F;
      P_TYPE(V_CONT).IP_LAN_01_A    := X.IP_LAN_01_A;
			P_TYPE(V_CONT).IP_LAN_01_C    := X.IP_LAN_01_C;
      
    END LOOP;
          
    IF P_TYPE.COUNT > 0 THEN
      
      FOR I IN P_TYPE.FIRST .. P_TYPE.LAST LOOP
      
        IF P_TYPE(I).IP_LAN_01_C = 'ERRO' THEN
				
          IF P_TYPE(I).IP_LAN_01_A = 'SIM' THEN
            
            UPDATE EV_COMPARA_SOLIC_BKB
               SET IP_LAN_01_I = P_TYPE(I).IP_LAN_01_F_A
             WHERE COD_SOLIC = P_TYPE(I).COD_SOLIC;

          ELSIF P_TYPE(I).IP_LAN_01_A = 'NÃO' THEN
					
            UPDATE EV_COMPARA_SOLIC_BKB
               SET IP_LAN_01_F = P_TYPE(I).IP_LAN_01_F_A
             WHERE COD_SOLIC = P_TYPE(I).COD_SOLIC;
						 
          END IF;
        END IF;
      END LOOP;
    END IF;
        
  EXCEPTION
    WHEN DUP_VAL_ON_INDEX THEN
      P_CD_RETORNO  := 3;
      P_DS_MENSAGEM := 'Registro com chave duplicada!! PROC_UPD_COMPARA_SOLIC';
      ROLLBACK;
    WHEN OTHERS THEN
      P_CD_RETORNO  := 9999;
      P_DS_MENSAGEM := 'PROC_QRY_COMPARA_SOLIC: '|| SQLERRM;
      ROlLBACK;
  END PROC_QRY_COMPARA_SOLIC;

END PACK_COMPARA_SOLIC;
Desde já agradeço.

:)
Avatar do usuário
dr_gori
Moderador
Moderador
Mensagens: 5024
Registrado em: Seg, 03 Mai 2004 3:08 pm
Localização: Portland, OR USA
Contato:
Thomas F. G

Você já respondeu a dúvida de alguém hoje?
https://glufke.net/oracle/search.php?search_id=unanswered

Acredito que tem um bug na sua lógica. Provavelmente o UPDATE que você faz está mudando os campos que são utilizados pra decidir se deve ou não atualizar.

Eu olharia aqui:

Selecionar tudo

      CASE WHEN EVS1.IP_LAN_01_A = 'SIM' THEN
          CASE WHEN NVL(TO_CHAR(EVS2.IP_LAN_01_F), 'NULL') = NVL(TO_CHAR(EVS1.IP_LAN_01_I), 'NULL') THEN 'OK' ELSE 'ERRO' END 
        ELSE -- NÃO É ALTERADO
          CASE WHEN NVL(TO_CHAR(EVS2.IP_LAN_01_F), 'NULL') = NVL(TO_CHAR(EVS1.IP_LAN_01_F), 'NULL') THEN 'OK' ELSE 'ERRO' END 
        END AS IP_LAN_01_C
e aqui

Selecionar tudo

 WHERE (EVS1.IP_LAN_01_A = 'SIM' AND NVL(TO_CHAR(EVS2.IP_LAN_01_F), 'NULL') <> NVL(TO_CHAR(EVS1.IP_LAN_01_I), 'NULL'))
           OR (EVS1.IP_LAN_01_A = 'NÃO' AND NVL(TO_CHAR(EVS2.IP_LAN_01_F), 'NULL') <> NVL(TO_CHAR(EVS1.IP_LAN_01_F), 'NULL'))
lucasesr
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 10
Registrado em: Ter, 06 Nov 2012 1:56 pm

dr_gori,

Retirei o WHERE do cursor e comentei o seguinte código

Selecionar tudo

CASE WHEN EVS1.IP_LAN_01_A = 'SIM' THEN
    CASE WHEN NVL(TO_CHAR(EVS2.IP_LAN_01_F), 'NULL') = NVL(TO_CHAR(EVS1.IP_LAN_01_I), 'NULL') THEN 'OK' ELSE 'ERRO' END -- IP_LAN_01_C_FA_I
  ELSE -- NÃO É ALTERADO
    CASE WHEN NVL(TO_CHAR(EVS2.IP_LAN_01_F), 'NULL') = NVL(TO_CHAR(EVS1.IP_LAN_01_F), 'NULL') THEN 'OK' ELSE 'ERRO' END -- IP_LAN_01_C_FA_F
  END AS IP_LAN_01_C
E nos IFs que antes eu buscava pelo campo IP_LAN_01_C, que foi comentado. Agora faço da seguinte maneira.

Selecionar tudo

FOR I IN P_TYPE.FIRST .. P_TYPE.LAST LOOP

	IF P_TYPE(I).IP_LAN_01_A = 'SIM' THEN
		IF P_TYPE(I).IP_LAN_01_F_A <> P_TYPE(I).IP_LAN_01_I THEN

			UPDATE EV_COMPARA_SOLIC_BKB
				 SET IP_LAN_01_I = P_TYPE(I).IP_LAN_01_F_A
			 WHERE COD_SOLIC = P_TYPE(I).COD_SOLIC;

		END IF;
		
	ELSIF P_TYPE(I).IP_LAN_01_A = 'NÃO' THEN
		IF P_TYPE(I).IP_LAN_01_F_A <> P_TYPE(I).IP_LAN_01_F THEN

			UPDATE EV_COMPARA_SOLIC_BKB
				 SET IP_LAN_01_F = P_TYPE(I).IP_LAN_01_F_A
			 WHERE COD_SOLIC = P_TYPE(I).COD_SOLIC;

		END IF;
	END IF;
	
END LOOP;
Ao executar, continua com o mesmo problema, atualiza alguns registros e outros não. :?
Avatar do usuário
stcoutinho
Moderador
Moderador
Mensagens: 850
Registrado em: Qua, 11 Mai 2011 5:15 pm
Localização: são Paulo - SP

lucaser,

Posso lhe dar uma sugestão?

Faça uma pequena alteração na sua procedure para avaliar o que está sendo executado:
1) Crie uma tabela: CREATE TABLE TB_SQL (COMANDO_SQL VARCHAR2(4000) NULL);;
2) No inicio da sua procedure:
2.1) Na área de declaração (antes do BEGIN), crie uma variavel W_SQL VARCHAR2(4000);;
2.2) Logo após o BEGIN, insira esta linha de comando: EXECUTE IMMEDIATE 'TRUNCATE TABLE TB_SQL';
2.3) Logo após o primeiro UPDATE, insira estas linhas:
W_SQL := 'UPDATE EV_COMPARA_SOLIC_BKB SET IP_LAN_01_I = '||P_TYPE(I).IP_LAN_01_F_A||
' WHERE COD_SOLIC = '||P_TYPE(I).COD_SOLIC||';';
INSERT INTO TB_SQL VALUES (W_SQL);
COMMIT;


2.4) Logo após o segundo UPDATE, insira estas linhas:
W_SQL := 'UPDATE EV_COMPARA_SOLIC_BKB SET IP_LAN_01_F = '||P_TYPE(I).IP_LAN_01_F_A||
' WHERE COD_SOLIC = '||P_TYPE(I).COD_SOLIC||';';
INSERT INTO TB_SQL VALUES (W_SQL);
COMMIT;

3) Execute a sua procedure;
4) Faça um SELECT COMANDO_SQL FROM TB_SQL;
5) Monte um script SQL com esta estrutura:
SPOOL UPDATE.LOG
SET FEEDBACK ON;
SET ECHO ON;
<<< MASSA COMANDOS UPDATE>>
COMMIT;
SPOOL OFF;

6) Execute este script no SQL*PLUS;
7) Avalie os resultados gerados no arquivo LOG
Lembre-se: você está fazendo dois updates em uma mesma tabela, atualizando duas colunas diferentes da mesma tabela. Sua rotina então pode ter feito - por exemplo - 1000 updates, mas afetado somente 500 registros.

Abraços,

Sergio Coutinho
Responder
  • Informação
  • Quem está online

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