Procedure - HELP

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
jedi_pereira
Rank: Programador Júnior
Rank: Programador Júnior
Mensagens: 16
Registrado em: Ter, 04 Dez 2007 2:12 pm
Localização: São Carlos - SP

olá pessoal,

estou com 2 problemas no procedure abaixo (sendo que gostaria que me ajudassem com o mais "grave")
ao montar o Quadro Comparativo, em vez de aparecer a quantidade de produtos/peças compradas, aparece o numero que foi pedido.

grato pela ajuda,
Pereira

script da procedure:

Selecionar tudo

create or replace procedure quadrocomparativo (ICODCOLIGADA INTEGER,
                                               IIDMOV INTEGER)

is

    -- Para Movimentos relacionados
    coligada              number(9,0);
    controle              number(9,0);
    rastreia              number(9,0);
    usuario               varchar2(50);
    movimento             number(9,0);
    codmovimento          varchar2(20);
    observa               varchar2(255);
    responsavel           varchar2(60);
    aprovador             varchar2(60);
    datamov               date;
    dataaprova            date;
    horaaprova            date;
    
    -- Para quadro comparativo
    quantidade_efetivada  number(9,4);
    melhor_compra         number(9,4);
    valor_orcado          number(9,4);
    id_trf                number(10);
    id_prj                number(10);
    desc_tarefa           varchar2(100);
    fornecedor_1          varchar2(20);
    fornecedor_2          varchar2(20);
    fornecedor_3          varchar2(20);
    fornecedor_4          varchar2(20);
    preço_1               number(9,4);
    preço_2               number(9,4);
    preço_3               number(9,4);
    preço_4               number(9,4);
    desconto_1            number(9,4);
    desconto_2            number(9,4);
    desconto_3            number(9,4);
    desconto_4            number(9,4);    
    quantidade_1          number(9,4);
    quantidade_2          number(9,4);
    quantidade_3          number(9,4);
    quantidade_4          number(9,4);
    
    auxCODCOLIGADA        number;
    auxIDMOV              number;

begin

  -- Movimentos relacionados (tabela Z_MOVRELAC)  
  begin
    -- Registra as variáveis
    coligada  := ICODCOLIGADA;
    movimento := IIDMOV;
    
    -- Limpa a tabela para esta coligada, movimento
    delete z_movrelac where codcoligada = coligada and idmov = movimento;
    delete z_quadro_comparativo where codcoligada = coligada and idmov = movimento;
    
    -- Registra o próprio movimento
    codmovimento := null;
    begin
      select codtmv into codmovimento
        from tmov
       where codcoligada = coligada
         and idmov = movimento;
    exception
      when others then null;
    end;
       
    -- Registrando a observação
    observa := null;
    begin
      select historicocurto into observa
        from tmovhistorico
       where codcoligada = coligada
         and idmov = movimento;
    exception
      when others then null;
    end;
       
    -- Registrando usuário responsável 
    usuario := null;
    begin
      select codusuario into usuario
        from tmov
      where codcoligada = coligada
        and idmov = movimento;
    exception
      when others then null;
    end;
    
    -- Nome do usuário responsavel
    responsavel := null;
    begin
      select nome into responsavel
        from gusuario
       where codusuario = usuario;
    exception
      when others then null;
    end;
  
    -- Registrando o usuário aprovador
    usuario := null;
    begin
      select codusuario into usuario
        from tmovaprova
       where codcoligada = coligada
         and idmov = movimento;
    exception
      when others then null;
    end;
    
    -- Nome do usuário aprovador
    aprovador := null;
    begin
      select nome into aprovador
        from gusuario
       where codusuario = usuario;
    exception
      when others then null;
    end;
    
    -- Data do movimento
    datamov := null;
    begin
      select dataemissao into datamov
        from tmov
       where codcoligada = coligada
         and idmov = movimento;
    exception
      when others then null;
    end;
    
    -- Data da aprovação
    dataaprova := null;
    begin
      select dataaprovacao into dataaprova
        from tmovaprova
       where codcoligada = coligada
         and idmov = movimento;        
    exception
      when others then null;
    end;
    
    -- Hora aprovação
    horaaprova := null;
    begin
      select horarioaprovacao into horaaprova
        from tmovaprova
       where codcoligada = coligada
         and idmov = movimento;
    exception
      when others then null;
    end;
    
    -- Preenchendo a tabela:
    insert into z_movrelac
                (CODCOLIGADA,
                 IDMOV, 
                 IDMOVRELAC,
                 COLIGADAMOVRELAC,
                 CODTMV,
                 OBSERVACAO,
                 USUARIO,
                 DATA,
                 APROVADOR,
                 DATAAPROV,
                 HORAAPROV)
           values
                (COLIGADA,
                 MOVIMENTO,
                 MOVIMENTO,
                 COLIGADA,
                 CODMOVIMENTO,
                 OBSERVA,
                 RESPONSAVEL,
                 DATAMOV,
                 APROVADOR,
                 DATAAPROVA,
                 HORAAPROVA);    
    
    -- Registrando os movimentos subsequentes
    -- Seta a variável controle para o id do movimento
    rastreia := movimento;
    
    while rastreia is not null loop 
    
      begin
      
        for subseq in (select * from tmovrelac where idmovdestino = rastreia and codcoldestino = coligada)
          loop

            begin
              auxidmov := subseq.idmovorigem;
              auxcodcoligada := subseq.codcolorigem;
              -- Registrando o codigo do movimento
              codmovimento := null;
              begin
                select codtmv into codmovimento
                  from tmov
                 where codcoligada = auxcodcoligada
                   and idmov = auxidmov
                   and status <> 'C';
              exception
                when others then null;
              end;
                 
              -- Registrando a observação
              observa := null;
              begin
                select historicocurto into observa
                  from tmovhistorico
                 where codcoligada = auxcodcoligada
                   and idmov = auxidmov;
              exception
                when others then null;
              end;             
              -- Registrando usuário responsável 
              usuario := null;
              begin
                select codusuario into usuario
                  from tmov
                where codcoligada = auxcodcoligada
                  and idmov = auxidmov;
              exception
                when others then null;
              end;
              
              -- Nome do usuário responsavel
              responsavel := null;
              begin
                select nome into responsavel
                  from gusuario
                 where codusuario = usuario;
              exception
                when others then null;
              end;
              
              -- Registrando o usuário aprovador
              usuario := null;
              begin
                select codusuario into usuario
                  from tmovaprova
                 where codcoligada = auxcodcoligada
                   and idmov = auxidmov;
              exception
                when others then null;
              end;
              
              -- Nome do usuário aprovador
              aprovador := null;
              begin
                select nome into aprovador
                  from gusuario
                 where codusuario = usuario;
              exception
                when others then null;
              end;
              
              -- Data do movimento
              datamov := null;
              begin
                select dataemissao into datamov
                  from tmov
                 where codcoligada = auxcodcoligada
                   and idmov = auxidmov;
              exception
                when others then null;
              end;
              
              -- Data da aprovação
              dataaprova := null;
              begin
                select dataaprovacao into dataaprova
                  from tmovaprova
                 where codcoligada = auxcodcoligada
                   and idmov = auxidmov;        
              exception
                when others then null;
              end;
              
              -- Hora aprovação
              horaaprova := null;
              begin
                select horarioaprovacao into horaaprova
                  from tmovaprova
                 where codcoligada = auxcodcoligada
                   and idmov = auxidmov;
              exception
                when others then null;
              end;
              
              -- Preenchendo a tabela:
              if codmovimento is not null
                then
                  insert into z_movrelac
                              (CODCOLIGADA,
                               IDMOV,
                               IDMOVRELAC,
                               COLIGADAMOVRELAC,
                               CODTMV,
                               OBSERVACAO,
                               USUARIO,
                               DATA,
                               APROVADOR,
                               DATAAPROV,
                               HORAAPROV)
                         values
                              (COLIGADA,
                               MOVIMENTO,
                               auxidmov,
                               auxcodcoligada,
                               CODMOVIMENTO,
                               OBSERVA,
                               RESPONSAVEL,
                               DATAMOV,
                               APROVADOR,
                               DATAAPROVA,
                               HORAAPROVA);
              end if;
              
              -- Roda o loop novamente trocando destino por origem para saber se existem mais movimentos subsequentes relacionados.                     

            end;
            
          end loop;

          select idmovorigem into rastreia from tmovrelac where idmovdestino = rastreia and codcoldestino = coligada;
          
      exception
      when others then
        rastreia := null;
      end;
      
      -- Fim dos Movimentos subsequentes
    end loop;
      
    -- Registrando os movimentos consequentes
    -- Seta a variável controle para o id do movimento
    rastreia := movimento;

    -- Inicia a busca
    while rastreia is not null loop
    
      begin
        select codcoldestino,idmovdestino into auxcodcoligada, auxidmov from tmovrelac where idmovorigem = rastreia and codcolorigem = coligada;
        
        -- Registrando o codigo do movimento
        codmovimento := null;
        begin
          select codtmv into codmovimento
            from tmov
           where codcoligada = auxcodcoligada
             and idmov = auxidmov
             and status <> 'C';
        exception
          when others then null;
        end;
           
        -- Registrando a observação
        observa := null;
        begin
          select historicocurto into observa
            from tmovhistorico
           where codcoligada = auxcodcoligada
             and idmov = auxidmov;
        exception
          when others then null;
        end;             
        -- Registrando usuário responsável 
        usuario := null;
        begin
          select codusuario into usuario
            from tmov
          where codcoligada = auxcodcoligada
            and idmov = auxidmov;
        exception
          when others then null;
        end;
        
        -- Nome do usuário responsavel
        responsavel := null;
        begin
          select nome into responsavel
            from gusuario
           where codusuario = usuario;
        exception
          when others then null;
        end;

        -- Registrando o usuário aprovador
        usuario := null;
        begin
          select codusuario into usuario
            from tmovaprova
           where codcoligada = auxcodcoligada
             and idmov = auxidmov;
        exception
          when others then null;
        end;
        
        -- Nome do usuário aprovador
        aprovador := null;
        begin
          select nome into aprovador
            from gusuario
           where codusuario = usuario;
        exception
          when others then null;
        end;
        
        -- Data do movimento
        datamov := null;
        begin
          select dataemissao into datamov
            from tmov
           where codcoligada = auxcodcoligada
             and idmov = auxidmov;
        exception
          when others then null;
        end;
        
        -- Data da aprovação
        dataaprova := null;
        begin
          select dataaprovacao into dataaprova
            from tmovaprova
           where codcoligada = auxcodcoligada
             and idmov = auxidmov;        
        exception
          when others then null;
        end;
        
        -- Hora aprovação
        horaaprova := null;
        begin
          select horarioaprovacao into horaaprova
            from tmovaprova
           where codcoligada = auxcodcoligada
             and idmov = auxidmov;
        exception
          when others then null;
        end;
        
        -- Preenchendo a tabela:
        if codmovimento is not null
          then
            insert into z_movrelac
                        (CODCOLIGADA,
                         IDMOV, 
                         IDMOVRELAC,
                         COLIGADAMOVRELAC,
                         CODTMV,
                         OBSERVACAO,
                         USUARIO,
                         DATA,
                         APROVADOR,
                         DATAAPROV,
                         HORAAPROV)
                   values
                        (COLIGADA,
                         MOVIMENTO,
                         auxidmov,
                         auxcodcoligada,
                         CODMOVIMENTO,
                         OBSERVA,
                         RESPONSAVEL,
                         DATAMOV,
                         APROVADOR,
                         DATAAPROVA,
                         HORAAPROVA);
        end if;

        -- Roda o loop novamente trocando destino por origem para saber se existem mais movimentos consequentes relacionados.                     
        rastreia := auxidmov;
        coligada := auxcodcoligada;
        
      Exception
        When Others then                 
          rastreia := null;
          
      end;
    -- Fim dos Movimentos Consequentes
    
    end loop;
    
    -- Só no fim grava a Z_MOVRELAC
    commit;
    -- Fim dos movimentos relacionados
  end;
  

  
  ------------------------------------------------------------------------------------------------------------------------------
  -- Cotação - Quadro Comparativo
  -- Para cada produto
  for produto in (select distinct (idprd)
                    from tcitmorcamento
                   where codcoligada = coligada
                     and idmov in (select idmovrelac
                                     from z_movrelac
                                    where codcoligada = coligada
                                      and idmov = movimento)
                  )
    loop
      begin
        -- Registra a quantidade total negociada do produto
        quantidade_efetivada := null;
        begin
          select sum (NVL(b.quantidade,0)) into quantidade_efetivada
            from tcitmorcamento a, titmmov b
           where a.codcoligada = coligada
             and a.codcoligada = b.codcoligada
             and a.idmov       = b.idmov
             and a.nseqitmmov  = b.nseqitmmov
             and a.idmov in (select idmovrelac
                               from z_movrelac
                              where codcoligada = coligada
                                and idmov = movimento)
             and a.idprd = produto.idprd
             and a.cfovencedor = 1;
          exception
             when others then null;
        end;
        
        -- Registra a melhor compra para o produto nos ultimos 12 meses
        melhor_compra := null;
        begin
          select min (valnegociado) into melhor_compra
            from tcitmorcamento
           where idprd = produto.idprd
             and valnegociado <> 0
             and idmov in (select idmov from tmov
                                        where dataemissao > (TRUNC(sysdate) -365));
        exception
          when others then null;
        end;
                                      
        -- Valor orçado se presente no movimento
        begin
          select precounitario into valor_orcado
            from titmmov
           where codcoligada = coligada
             and idmov = (select min(idmovrelac)
                            from z_movrelac
                           where codcoligada = coligada
                             and idmov = movimento)
             and idprd = produto.idprd;
        exception
          when others then null;
        end;
        
        
        -- * * * > > > Colocar centro de custo associado no ítem ao invés de tarefa
        --tabela: "tmovratccu", buscando na "gccusto" o nome do centro de custo,
        -- lembrando que existe rateio habilitado, prever se só existe uma linha e com
        --100% de rateio (relação 1 pra 1) e só trazer se for nesta condição.
        
        
        -- Tarefa associada (para compras integradas com o Solum) IDTRF
           begin
          select idtrf into id_trf
            from titmmov
           where codcoligada = coligada
             and idmov = (select min(idmovrelac)
                            from z_movrelac
                           where codcoligada = coligada
                             and idmov = movimento)
             and idprd = produto.idprd;
        exception
          when others then null;
        end;
        
        -- Projeto associado IDPRJ
           begin
          select idprj into id_prj
            from titmmov
           where codcoligada = coligada
             and idmov = (select min(idmovrelac)
                            from z_movrelac
                           where codcoligada = coligada
                             and idmov = movimento)
             and idprd = produto.idprd;
        exception
          when others then null;
        end;

        -- Ainda para a tarefa, verifica no Solum o nome da tarefa.
        begin
          select nome into desc_tarefa
            from mtrf
           where codcoligada = coligada
             and idprj = id_prj
             and idtrf = id_trf;
        exception
          when others then null;
        end;
        
        -- Para cada fornecedor deste produto na cotação
        -- Inicia a variável de controle
        controle := 1;
        for fornecedor in (select codcfo,valnegociado,percdescontonegociado,CFOVENCEDOR
                             from tcitmorcamento
                            where codcoligada = coligada
                              and idmov in (select idmovrelac
                                              from z_movrelac
                                             where codcoligada = coligada
                                               and idmov = movimento)
                              and idprd = produto.idprd
                         group by codcfo,valnegociado,percdescontonegociado,CFOVENCEDOR
                         order by cfovencedor desc,codcfo)
          loop
            -- Registra o fornecedor 1, preço 1, desconto 1
            if controle = 1
              then
                begin
                  fornecedor_1 := fornecedor.codcfo;
                  preço_1      := fornecedor.valnegociado;
                  desconto_1   := fornecedor.percdescontonegociado;
                  quantidade_1 := quantidade_efetivada;
                end;
            end if;
            
            -- Registra o fornecedor 2, preço 2, desconto 2
            if controle = 2
              then
                begin
                  fornecedor_2 := fornecedor.codcfo;
                  preço_2      := fornecedor.valnegociado;
                  desconto_2   := fornecedor.percdescontonegociado;
                  quantidade_2 := 0;
                end;
            end if;
            
            -- Registra o fornecedor 3, preço 3, desconto 3            
            if controle = 3
              then
                begin
                  fornecedor_3 := fornecedor.codcfo;
                  preço_3      := fornecedor.valnegociado;
                  desconto_3   := fornecedor.percdescontonegociado;
                  quantidade_3 := 0;                  
                end;
            end if;
            
            -- Registra o fornecedor 4, preço 4, desconto 4
            if controle = 4
              then
                begin
                  fornecedor_4 := fornecedor.codcfo;
                  preço_4      := fornecedor.valnegociado;
                  desconto_4   := fornecedor.percdescontonegociado;
                  quantidade_4 := 0;                  
                end;
            end if;


          controle := controle +1;            
          end loop;
        
      end;
      -- Grava a tabela para cada produto da cotação:
      insert into z_quadro_comparativo
                  (CODCOLIGADA,
                   IDMOV,
                   CODPRODUTO,
                   QUANTIDADE,
                   MELHORCOMPRA,
                   ORCADO,
                   TAREFA,
                   FORNECEDOR1,
                   PRECO1,
                   DESCONTO1,
                   QUANTIDADE1,
                   FORNECEDOR2,
                   PRECO2,
                   DESCONTO2,
                   QUANTIDADE2,
                   FORNECEDOR3,
                   PRECO3,
                   DESCONTO3,
                   QUANTIDADE3,
                   FORNECEDOR4,
                   PRECO4,
                   DESCONTO4,
                   QUANTIDADE4)
            values
                  (coligada,
                   movimento,
                   produto.idprd,
                   quantidade_efetivada,
                   melhor_compra,
                   valor_orcado,
                   desc_tarefa,
                   fornecedor_1,
                   preço_1,
                   desconto_1,
                   quantidade_1,
                   fornecedor_2,
                   preço_2,
                   desconto_2,
                   quantidade_2,
                   fornecedor_3,
                   preço_3,
                   desconto_3,
                   quantidade_3,
                   fornecedor_4,
                   preço_4,
                   desconto_4,
                   quantidade_4
                   );
                   

    -- Fim dos produtos da cotação
    end loop;
  -- Commit na segunda tabela
  commit;
  
end;
Trevisolli
Moderador
Moderador
Mensagens: 2016
Registrado em: Qua, 12 Jan 2005 3:25 pm
Localização: Araraquara - SP
Abraço,

Trevisolli
OCA Oracle PL/SQL Developer Certified Associate
OCP Oracle Forms Developer Certified Professional
Araraquara-SP

Brother, uma dica:

Deu uma olhada nas Exceptions, onde podem retornar null?
When others then null ???

Pode não estar retornando valores para os loops posteriores.
jedi_pereira
Rank: Programador Júnior
Rank: Programador Júnior
Mensagens: 16
Registrado em: Ter, 04 Dez 2007 2:12 pm
Localização: São Carlos - SP

pelo que vi, o problema não é no exception

eu acho que é nessa parte:

Selecionar tudo

-- Registra a quantidade total negociada do produto
        quantidade_efetivada := null;
        begin
          select sum (NVL(b.quantidade,0)) into quantidade_efetivada
            from tcitmorcamento a, titmmov b
           where a.codcoligada = coligada
             and a.codcoligada = b.codcoligada
             and a.idmov       = b.idmov
             and a.nseqitmmov  = b.nseqitmmov
             and a.idmov in (select idmovrelac
                               from z_movrelac
                              where codcoligada = coligada
                                and idmov = movimento)
             and a.idprd = produto.idprd
             and a.cfovencedor = 1;
        exception
          when others then null;
        end;
quando faz o a.idmov in (...), porque está fazendo um select na tabela z_movrelac, que tem os itens pedidos (não os comprados)... tentei alterar isso, mas dá erro na execução:

Selecionar tudo

ORA-01400: cannot insert NULL into ("RM"."Z_QUADRO_COMPARATIVO"."QUANTIDADE")
ORA-06512: at "RM.QUADROCOMPARATIVO", line 663
ORA-06512: at line 8
a linha 663 é insert into z_quadro_comparativo...

vlw
Trevisolli
Moderador
Moderador
Mensagens: 2016
Registrado em: Qua, 12 Jan 2005 3:25 pm
Localização: Araraquara - SP
Abraço,

Trevisolli
OCA Oracle PL/SQL Developer Certified Associate
OCP Oracle Forms Developer Certified Professional
Araraquara-SP

Então brother, debuga e testa este trecho.
Deve estar não retornando nada e, a exception mascarando... teu item de quantidade deve ser not null e, está tentando inserir null.
jedi_pereira
Rank: Programador Júnior
Rank: Programador Júnior
Mensagens: 16
Registrado em: Ter, 04 Dez 2007 2:12 pm
Localização: São Carlos - SP

desculpa, devo ta sendo muito chato

mas o Debug ta dando esse erro:

Selecionar tudo

ORA-30683: failure establishing connection to debugger
ORA-12541: TNS:no listener
ORA-06512: at "SYS.DBMS_DEBUG_JDWP", line 68
ORA-06512: at line 1
que diabos é isso??
(nunca tinha usado o Oracle SQL Developer)

grato
Trevisolli
Moderador
Moderador
Mensagens: 2016
Registrado em: Qua, 12 Jan 2005 3:25 pm
Localização: Araraquara - SP
Abraço,

Trevisolli
OCA Oracle PL/SQL Developer Certified Associate
OCP Oracle Forms Developer Certified Professional
Araraquara-SP

Então brother,

Não utilizo aqui o SQL DEveloper...
Você deve estar utilizando o Debug dele, é isso?

Uma forma mais fácil seria colocar mensagens na tua procedure, e chamá-la no SQL Developer.

Por exemplo, no trecho onde pode estar retornando null, colocar mensagens como por exemplo:

Selecionar tudo

DBMS_OUTPUT.PUT_LINE('Valor do campo XXX ' || coligada );
jedi_pereira
Rank: Programador Júnior
Rank: Programador Júnior
Mensagens: 16
Registrado em: Ter, 04 Dez 2007 2:12 pm
Localização: São Carlos - SP

consegui resolver a quantidade de produto... valeu

agora o unico problema é que dependendo do produto, aparece 2x no quadro comparativo... chega a ser engraçado... porque em 4 relatorios q fiz pra ver (produtos diferentes), só em 1 que dá esse problema de item aparecendo 2x


mas agradeço sua ajuda
jedi_pereira
Rank: Programador Júnior
Rank: Programador Júnior
Mensagens: 16
Registrado em: Ter, 04 Dez 2007 2:12 pm
Localização: São Carlos - SP

explicando melhor o problema (devia ter um editar pra não criar outra resposta)


o único problema que resta é que dependendo do produto, no quadro comparativo, ele aparece 2x (o primeiro produto)
- dados do primeiro produto
- dados do primeiro produto (aparece repetido apenas em poucos casos)
- dados do segundo produto (se existir)
- dados do terceiro produto (se existir)
...

mas a repetição não afeta o valor total das compras (ou seja, o item repetido não é incluido no total)

se alguém tiver alguma ideia, porque se fosse sempre, era facil de achar o erro...

grato
jedi_pereira
Rank: Programador Júnior
Rank: Programador Júnior
Mensagens: 16
Registrado em: Ter, 04 Dez 2007 2:12 pm
Localização: São Carlos - SP

achei o erro... era na geração do relatório e não no código da procedure...

e um edit aqui no forum faz falta
Responder
  • Informação