Tabelas de Cabeçalhos e de Itens

No seu primeiro mês de trabalho como programador ABAP muito provavelmente você terá que trabalhar com documentos SAP, como por exemplo Ordem de Vendas, Pedidos de Compras, Documentos Contábeis dentre outros.

Esses documentos são geralmente armazenados em tabelas separando os dados do cabeçalho e outra para dados dos itens, por exemplo Ordem de Vendas (VBAK e VBAP), Pedidos de Compra (EKKO e EKPO) e Documentos Contábeis (BKPF e BSEG).

Nesse post, vou mostrar algumas técnicas para manipular dados em estruturas como essas.

Usando Duas Tabelas Internas

A primeira técnica é usando duas tabelas internas e daí usar o comando AT NEW para identificar quando o registro representa um novo documento. No exemplo abaixo estou usando duas tabelas EKKO e EKPO, tabelas de um pedido de compra.

Esse exemplo é muito simples e direto. Não esqueça de garantir que as tabelas estejam ordenadas pela chave de busca e de usar a cláusula BINARY SEARCH.

Usando Uma Tabela Interna

Nessa técnica estou fazendo apenas um único SELECT com JOIN nas duas tabelas em questão. Com isso o LOOP na tabela interna fica simplificado, não necessitando fazer o READ TABLE.

Cláusula do JOIN alterada. Foi incluído o campo MANDT. Obrigado Antélio.

Aqui não é obrigatório ordenar a tabela interna, pois ela já vem ordenada do banco de dados.

Usando Duas Tabelas e Dois LOOPs

Essa técnica é bem controversa, o LOOP com cláusula WHERE não é indicado pois pode apresentar um certo impacto na performance. O código fica bem simples, mas há um consumo bem grande de processamento.

Nesse caso, o sistema a cada LOOP WHERE, faz um full table scan na internal table,  faz uma cópia dos registros selecionados na cláusula WHERE e daí executa o LOOP. Tudo de maneira transparente para o programador, mas isso pode representar um processamento desnecessário no programa. Para solucionar o problema, usamos a técnica abaixo.

Aqui descobrimos o index onde os registros da cláusula WHERE começam e iniciamos o LOOP dali. Usamos a estrutura AT LAST OF  para detectar que estamos “fora” da cláusula WHERE e sairmos do LOOP.

Com isso nenhum full table scan ou replicação de dados desnecessária em memória foi feita. Essa é outra técnica muito popular.

Essas técnicas devem com certeza fazer parte do arsenal de todo programador ABAP.

8 Responses

  1. Olá Furlan,

    Ótimo post! Quando saí da academia ABAP eu ficava perdido em como fazer um simples report, pois, embora eu tivesse visto LOOPs/SELECT, não achava que seria tão freqüente a criação de relatórios…

    Uma coisa que vejo frequentemente é o uso de FOR ALL ENTRIES, o que não é tão bem visto assim…

    Abraços!

  2. Antelio says:

    Furlan,
    No select com Inner Join, é necessário colocar o campo MANDT.

    []’s.

  3. Fábio Pagoti says:

    Esse post é um grande exemplo de:
    1) Como um simples requerimento pode ser atendido de diversas formas
    2) Como um código bem elaborado pode evitar problemas de desempenho
    3) “Best Pratices” usadas por desenvolvedores, como no último exemplo no qual se “caça” o índice correto para evitar processamento desnecessário.

    Parabéns Furlan!

  4. Pedro Paulo says:

    Sofri com isso no SIEC. Só um detalhe, que o AT NEW tem que ser usado no campo chave mais a esquerda, ou não? Caso ela nao for o campo mais da esquerda, o at new verificará se houve mudança em todos os campos a esquerda do camp configurado.

  5. Renato Kenzo says:

    Estava sofrendo isso até encontrar esse post, pois meu SIEC se inicia hoje, valeu pelo post Furlan, ah inclusive alguns exercícios do SIEC, levam sua assinatura.
    Parabéns Furlan.

  6. Cauê Yoshinaga says:

    Furlan,

    Na sua opinião, qual seria melhor JOIN ou For ALL ENTRIES?

    • furlan says:

      Depende da situação. Se você fizer o JOIN usando somente campos chaves e limitar o número de tabelas do join (no máximo 3 ou 4), o JOIN tem maior potencial para ser mais rápido.

      Agora imagine se a tabela do FOR ALL ENTRIES for muito grande. A string de SELECT que a interface de banco de dados envia para o gerenciado de banco de dados (Oracle, DB2, SQL Server etc.) ficará muito grande, sendo necessário vários SELECTs.

      Eu ainda vou escrever um post para explicar melhor isso.

  1. December 31, 2011

    […] Tabelas de Cabeçalhos e de Itens […]