quinta-feira, 17 de novembro de 2011

' Loop where ' ou ' Do Read table '

  REPORT zloopwowhere.

" Declaração das tabelas internas
DATA : it_ekko TYPE TABLE OF ekko,
       it_ekpo TYPE TABLE OF ekpo
      .

" Declaração das estruturas
DATA : st_ekko TYPE ekko,
       st_ekpo TYPE ekpo
      .

" Seleciona Cabeçalho do documento de compra
SELECT *
  FROM ekko
  INTO TABLE it_ekko
  UP TO 20 ROWS.

"  Toda vez que for usar o 'for all entries' a tabela tem que ser ordenada
" e sem duplicidade do campo que faz a ligação entre as tabela pela cláusula
" 'where' do select. Eu não fiz isso na it_ekko porque ela soh tem uma chave
" portanto não teria duplicidade e tb por ter somente uma chave ela ja
" vem ordenada direitinho, mas vou aproveitar e mostrar como fazer caso o
" campo 'EBELN' não fosse chave completa da tabela.....

  DELETE ADJACENT DUPLICATES FROM it_ekko COMPARING ebeln.
  SORT : it_ekko by ebeln .

"  observe que NESTE CASO não mudou nada rsrsrs


" Seleciona Item do documento de compras
SELECT *
  FROM ekpo
  INTO TABLE it_ekpo
  FOR ALL ENTRIES IN it_ekko
  WHERE ebeln = it_ekko-ebeln.

"  Quando você dá um 'Sort' numa tabela sem especificar por qual campo,
" o programa adota as chaves da tabela como critério de ordenação.
SORT : it_ekpo.



*&-Loop com loop(where)------------------------------------------Errado*
"  Loop no cabeçalho
LOOP AT it_ekko INTO st_ekko.

" Loop nos itens que tenham o ebeln iguais.
  LOOP AT it_ekpo INTO st_ekpo
    WHERE ebeln = st_ekko-ebeln.

*    Procedimento

  ENDLOOP.

ENDLOOP.
*&Porque está errado ?-------------------------------------------------*
*  Quando você executa um 'Loop' com 'Where' ele irá passar por todos os
* registros da tabela verificando a condição, se a tabela for grande, isso
* com certeza irá demorar muito...



*&-loop com read e Do---------------------------------------------Certo*
" Criação de uma variável local para receber o indice do registro na tabela
data : vl_tabix TYPE sy-tabix.

"  Loop no cabeçalho
LOOP AT it_ekko INTO st_ekko.

"  Read table com a chave para identificar o index do primeiro registro
" na condição desejada.
READ TABLE it_ekpo INTO st_ekpo
  WITH KEY ebeln = st_ekko-ebeln
" Só use 'Binary Search' em uma tabela Ordenada.
    BINARY SEARCH.

IF sy-subrc = 0.

" Variavel armazena valor do index.
  vl_tabix = sy-tabix.

"  Faça a leitura do registro pelo index informado.
DO.
  READ TABLE it_ekpo INTO st_ekpo
    INDEX vl_tabix.

"  Caso o registro trazido pelo 'Read table' esteja fora do desejado será
" executado o commando 'Exit' que força a saída do commando 'Do'.
  IF st_ekko-ebeln <> st_ekpo-ebeln
    or sy-subrc <> 0.
    exit.
  ENDIF.

*  Procedimento

" Adiciona +1 para o index para que seja feito o read do proximo registro.
  add 1 to vl_tabix.

ENDDO.

ENDIF.

ENDLOOP.
*&Porque está certo ?--------------------------------------------------*
*  O primeiro 'Read table' Identifica que existe arquivo e aponta para o
* primeiro registro com a condição desejada, o comando 'do' serve como laço
* para que seja lido todos os itens da condição, estando fora disso ele
* sai do processo e termina, portando lendo somente os arquivos necessarios
* sem precisar passar por toda tabela.

4 comentários:

  1. Olá Mauro. Você poderia também dar o loop na it_ekpo. No at new ebeln vc faz o read da it_ekko.

    Concordo que o seu método é útil e em alguns casos, o mais recomendado.

    Grande abraço e ótimo trabalho que você está fazendo.
    Vagnão

    ResponderExcluir
  2. Isso Mesmo Vagnão, eu vejo bastante isso, só não recomendo muito pra quem está começando senão pode perder referencia durante o processo do que é cabeçalho e do que é item.

    Mas é um comentário que caso for fazer manutenção iremos ver muito, Valeu a dica.

    ResponderExcluir
  3. Outra maneira de fazer a mesma coisa é da seguinte forma (é oq costumo usar):

    http://abap4kids.blogspot.com.br/2012/08/boas-praticas-para-loop-at-aninhados.html

    ResponderExcluir
  4. Legal Mauricio, Seu metodo substitui meu 'DO' pelo seu novo 'LOOP'..... Resultado igual de formas diferentes... Dahora !!!! Valeo por compartilhar isso.

    ResponderExcluir