1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

  2. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

Duvida for first e find first

Discussão em 'Progress 4GL' iniciado por brunoowr, Julho 23, 2018.

  1. brunoowr

    brunoowr Membro Participativo

    Gostaria de saber se há alguma diferença pratica entre essas duas formas de buscar um registro.

    Código:
    for first emitente
        where emitente.nome-abrev = "ABC" no-lock.
    end.
    Código:
    find first emitente
         where emitente.nome-abrev = "ABC" no-lock no-error.
    Também gostaria de saber, no caso do for, se há diferença entre utilizar "." ou ":" após o no-lock.
  2. rafael.andrade

    rafael.andrade Membro Master Moderador Equipe de Suporte

    Sobre o "." e o ":" é somente estético, então fica a critério do desenvolvedor.

    Já o FOR FIRST para o FIND FIRST há algumas diferenças.

    No FOR FIRST temos:
    - Só entra no código interno se o registro existe.
    - Permite ORDER BY
    - Funciona como bloco transacional, pra quem não gosta de criar blocos de forma explícita usando o DO TRANS.

    No FIND FIRST:
    - Só ordena registros por índices que já existem na tabela, se quiser trocar o índice precisa escrever USE-INDEX NomeDoIndice na query
    - Necessita de tratativa de registro ausente, ou seja, uso de "IF NOT AVAIL emitente THEN DO: [Exibe mensagem e tal]..."
    - Sempre é importante usar NO-ERROR e tratar se o registro não estiver disponível.
    - Há ainda a tratativa de registro bloqueado, quando se quer usar EXCLUSIVE-LOCK, adicionar NO-WAIT, sendo assim, caso o registro esteja em uso (LOCK) por outro usuário, retorna NOT AVAIL. Deve-se usar em conjunto com NO-ERROR.
  3. brunoowr

    brunoowr Membro Participativo

    Claro, há diferenças que parecem óbvias por isso não citei rsrs
    Minha dúvida era específico ao localizar registros, por exemplo: localizar item, emitente e pedido de uma nota para carregar todas as informações em uma tabela temporária.
    Resumindo: depende bastante da situação! hehe

    Muito obrigado!
  4. rafael.andrade

    rafael.andrade Membro Master Moderador Equipe de Suporte

    Na minha opinião, em 99,99% das vezes é melhor usar o FIND FIRST, o FOR FIRST é para aqueles casos em que não dá pra adicionar índice e precisa trazer registro numa ordem específica e outros
    casos muito específicos.

    Recomendo usar mais o FIND FIRST também porque com ele é possível tratar se o registro existe ou não, coisa que se usar o FOR FIRST o programa passa direto e acaba não preenchendo a temp-table
    como você disse, sem você saber.
  5. brunoowr

    brunoowr Membro Participativo

    Exatamente, no programa que vi o for first, poderia ser usado find first sem problema algum, na verdade achei só mais "bonito".
    Código:
            find first repres
                 where repres.nome-abrev = nota-fiscal.no-ab-reppri no-lock no-error.
    
            if not avail repres then next.
    
            for first tt-detalhado
                where tt-detalhado.cod-rep   = repres.cod-rep
                  and tt-detalhado.nr-linha  = item.nr-linha
                  and tt-detalhado.it-codigo = item.it-codigo exclusive-lock:
            end.
    
            if not avail tt-detalhado then do:
                create tt-detalhado.
                assign tt-detalhado.nr-linha    = item.nr-linha
                       tt-detalhado.lin-desc    = if avail lin-prod then lin-prod.descricao else ""
                       tt-detalhado.cod-rep     = repres.cod-rep
                       tt-detalhado.nome-repres = if avail repres then repres.nome-abrev else ""
                       tt-detalhado.regiao      = nota-fiscal.nome-ab-reg
                       tt-detalhado.it-codigo   = item.it-codigo
                       tt-detalhado.desc-item   = item.desc-item
                       tt-detalhado.un          = item.un.
            end.
  6. bootstrapmaster

    bootstrapmaster Moderator Moderador Equipe de Suporte

    Então, veja só, esse seu caso ai, na minha opinião é algo sem sentido, fazer um for first e depois tratar com avail ??????
    como disse o Rafael, na maioria dos casos, usar find first associado com o avail, eu utilizo muito for first e for last, quando tenho tabelas com data de validade por exemplo, uma tabela de preços com data de validade, vc quer saber o preço praticado na época, um for last acha facilmente esse tipo de registro.

    Ou, esse que eu uso muito, estou populando uma tabela, pra um relatorio por exemplo, e tem campos que SE EXISTIR o registro, preenche, se não deixa em branco, dai o for first é perfeito.

    Código:
                        for last cst_mp_tabela_preco_item
                            where cst_mp_tabela_preco_item.cod-emitente   = docum-est.cod-emitente
                              and cst_mp_tabela_preco_item.it-codigo      = item-doc-est.it-codigo
                              and cst_mp_tabela_preco_item.data_validade <= docum-est.dt-emissao:
                            assign cst_mp_tabela_preco_item.preco_unitario = cst_mp_nfe_item.preco_unitario_tabela.
                        end.
    
    Nesse codigo, estou pegando o preço unitario praticado na época em que a nota foi recebida, essa tabela cst_mp_tabela_preco_item é atualizada pelos gerentes, e quando vai fazer o recebimento das notas referente a uma determinada compra, caso o valor unitario da nota seja superior ao ORÇADO, trava o recebimento até o diretor dar um OK pra ela, então, os gerentes atualizam os preços unitarios informando a data em que os mesmos sofreram alteração, se vc usar for first, tem que inverter o sinal na clausula da data, para pegar até que dia essa tabela é valida
    Código:
                        for first cst_mp_tabela_preco_item
                            where cst_mp_tabela_preco_item.cod-emitente   = docum-est.cod-emitente
                              and cst_mp_tabela_preco_item.it-codigo      = item-doc-est.it-codigo
                              and cst_mp_tabela_preco_item.data_validade > docum-est.dt-emissao:
                            assign cst_mp_tabela_preco_item.preco_unitario = cst_mp_nfe_item.preco_unitario_tabela.
                        end.
    
    e tem ainda como vc usar algo como, procura por estabelecimento '101', caso não ache, pega o default, ai o for first ou for last é util também:
    Código:
    for first cst_param_cfop no-lock
        where (cst_param_cfop.cod_canal_venda       = cod_canal_venda        or cst_param_cfop.cod_canal_venda       = 999)
          and (cst_param_cfop.tipo_venda            = tipo_venda             or cst_param_cfop.tipo_venda            = 999)
          and (cst_param_cfop.tipo_material         = tipo_material          or cst_param_cfop.tipo_material         = 999)
          and (cst_param_cfop.pessoa                = pessoa                 or cst_param_cfop.pessoa                = 999)
          and (cst_param_cfop.Contribuinte_icms     = Contribuinte_icms      or cst_param_cfop.Contribuinte_icms     = 999)
          and (cst_param_cfop.inscricao_estadual    = inscricao_estadual     or cst_param_cfop.inscricao_estadual    = 999)
          and (cst_param_cfop.substituto_tributario = substituto_tributario  or cst_param_cfop.substituto_tributario = 999)
          and (cst_param_cfop.venda                 = venda                  or cst_param_cfop.venda                 = 999):
    end.
    
    Vixi, falei demais agora, me empolguei.
    Marildo de Mendonca e brunoowr curtiram isso.

Compartilhe esta Página