Análise e teste de código
Utilização correta de tipos de dados e conversões de tipo
Processamento de campos de caracteres
Uso de push-down de código no ABAP SQL
Melhorar o desempenho da tabela interna
Implementar verificações de autorização
Projetando código efetivo orientado a objetos
Definir e trabalhar com classes de exceção
Adicionar documentação à codificação ABAP

Execução de cálculos e processamento de string no ABAP SQL

Objectives

After completing this lesson, you will be able to:
  • Executar cálculos no banco de dados.
  • Execute o processamento de cadeia no banco de dados.

Expressões aritméticas

No ABAP SQL, as expressões aritméticas podem ser utilizadas como elementos da lista de campos.

O ABAP SQL suporta os quatro operadores básicos, colchetes e três aritméticas diferentes (número inteiro, decimal e ponto flutuante). O intervalo de valores e a precisão de resultados intermédios dependem fortemente da aritmética utilizada.

A aritmética é derivada dos operandos usados na expressão:

  • Se a expressão contiver apenas operandos inteiros, a expressão será uma expressão inteira e o resultado também será do tipo inteiro.
  • Assim que a expressão contiver um operando do tipo decimal (tipos Dictionary DEC, QUAN, CURR, tipo ABAP p), o resultado da expressão é do tipo DEC.
  • Se todos os operandos tiverem um tipo binário de ponto flutuante (tipo Dictionary FLTP, tipo ABAP f), a expressão é uma expressão de ponto flutuante e o resultado é do tipo FLTP.

Existem as seguintes restrições importantes:

  • O operador de divisão (/) só é permitido em expressões de ponto flutuante.
  • Não é possível utilizar tipos de ponto flutuante e outros tipos numéricos na mesma expressão.

Dica

Você pode usar qualquer operando numérico em uma expressão de ponto flutuante convertendo o tipo em FLTP usando CAST( ).

Exemplo: algumas expressões aritméticas no ABAP SQL

Este exemplo mostra dois exemplos de expressões aritméticas na lista de campos de uma instrução SELECT do ABAP SQL.

O campo SEATS_AVAILABLE é calculado subtraindo o número de assentos ocupados (campo de tabela SEATS_OCCUPIED) do número total de assentos nesse voo (campo de tabela SEATS_MAX). Como ambos os operandos são do tipo inteiro, o resultado dessa expressão também é um inteiro.

O campo PERCENTAGE_FLTP calcula a porcentagem de assentos ocupados como um número entre 0 e 100. Para isso, é necessário multiplicar o número de assentos ocupados com o literal 100 e dividir o resultado pelo número total de assentos. Uma vez que o operador de divisão só está disponível em expressões de ponto flutuante, todos os operandos devem ser convertidos no tipo FLTP. Como consequência, o resultado também é do tipo FLTP, que é exibido na notação científica por padrão.

Nota

O literal de número 100 tem o tipo inteiro e, portanto, também deve ser convertido para o tipo FLTP. Como alternativa, você pode definir uma constante do tipo f com o valor 100.0 e usar essa constante na expressão SQL.

Experimente: expressões aritméticas

  1. Crie uma nova classe global que implemente a interface IF_OO_ADT_CLASSRUN.
  2. Copie o seguinte snippet de código para a parte de implementação do método if_oo_adt_classrun~main( ):
    Code Snippet
    1234567891011121314151617181920
    SELECT FROM /dmo/flight FIELDS seats_max, seats_occupied, seats_max - seats_occupied AS seats_avaliable, ( CAST( seats_occupied AS FLTP ) * CAST( 100 AS FLTP ) ) / CAST( seats_max AS FLTP ) AS percentage_fltp WHERE carrier_id = 'LH' AND connection_id = '0400' INTO TABLE @DATA(result). out->write( EXPORTING data = result name = 'RESULT' ).
  3. Selecione CTRL + F3 para ativar a classe e F9 para executá-la como um aplicativo de console.
  4. Analise a saída do console.
  5. Tente suas próprias expressões aritméticas para se familiarizar com a sintaxe.

Funções numéricas

O ABAP SQL oferece várias funções integradas para complementar cálculos com expressões aritméticas. Uma lista completa pode ser encontrada na documentação de linguagem ABAP.

Algumas funções SQL numéricas importantes são as seguintes:

  • A função DIV( ) executa uma divisão de número inteiro (sem resto) e só permite valores inteiros como entrada.
  • A função MOD( ) retorna o resto do número inteiro dessa divisão.
  • A função DIVISION( ) permite qualquer entrada numérica, exceto para valores em ponto flutuante. A precisão do resultado decimal é indicada pelo terceiro parâmetro da função.
  • A função ROUND( ) permite arredondar explicitamente um valor numérico para uma determinada posição.

Exemplo: uso de funções numéricas no ABAP SQL

O exemplo ilustra o uso de funções numéricas no ABAP SQL. A função DIV( ) permite calcular o valor percentual como um número inteiro, enquanto a função DIVISION( ) retorna o resultado como um valor decimal.

Observe que DIV( ) corta o restante para que 48.78787… se torne 48. DIVISION( ), por outro lado, usa arredondamento comercial para arredondar para o número especificado de decimais, de modo que 48.7878… torna-se 48.79 em vez de 48.78.

Testar: funções numéricas

  1. Crie uma nova classe global que implemente a interface IF_OO_ADT_CLASSRUN.
  2. Copie o seguinte snippet de código para a parte de implementação do método if_oo_adt_classrun~main( ):
    Code Snippet
    1234567891011121314151617181920212223
    SELECT FROM /dmo/flight FIELDS seats_max, seats_occupied, ( CAST( seats_occupied AS FLTP ) * CAST( 100 AS FLTP ) ) / CAST( seats_max AS FLTP ) AS percentage_fltp, div( seats_occupied * 100 , seats_max ) AS percentage_int, division( seats_occupied * 100, seats_max, 2 ) AS percentage_dec WHERE carrier_id = 'LH' AND connection_id = '0400' INTO TABLE @DATA(result). out->write( EXPORTING data = result name = 'RESULT' ).
  3. Selecione CTRL + F3 para ativar a classe e F9 para executá-la como um aplicativo de console.
  4. Analise a saída do console.
  5. Posicione o cursor em uma das funções numéricas (por exemplo, setor de atividade e selecione F1 para abrir a documentação.
  6. Procure outras funções numéricas na documentação e experimente-as para se familiarizar com suas possibilidades.

Processamento de cadeia

No ABAP, o operador && permite combinar argumentos em forma de caractere em uma cadeia longa. Você também pode usar este operador no ABAP SQL para executar as operações de concatenação já no banco de dados. No primeiro exemplo, o título, o primeiro nome e o sobrenome de um cliente são combinados com o nome completo. No segundo exemplo, rua, código postal e nome da cidade são combinados com o endereço do cliente. Uma vez que && não adiciona separadores de qualquer tipo, os espaços em branco devem ser adicionados manualmente.

Funções de processamento de cadeia

O ABAP SQL também oferece muitas funções integradas para processamento de cadeia. Uma lista completa pode ser encontrada na documentação de linguagem ABAP.

Algumas funções de string importantes no ABAP SQL são as seguintes:

  • A função CONCAT( ) concatena duas cadeias (sem espaços em branco).
  • A função CONCAT_WITH_SPACE( ) faz o mesmo, mas insere um número especificado de espaços em branco no meio.
  • As funções UPPER( ) e LOWER( ) transformam um argumento em maiúsculas/minúsculas.
  • A função INITCAP( ) funciona como LOWER( ), mas transforma a primeira letra de cada palavra em maiúsculas.
  • As funções LEFT( ) extraem os primeiros n caracteres de um determinado argumento. RIGHT( ) faz o mesmo, mas começa da direita.
  • A função SUBSTRING( ) extrai um determinado número de caracteres, começando a partir de uma determinada posição.

O exemplo constrói o endereço de um cliente concatenando rua, código postal e cidade. Ele faz isso de duas maneiras diferentes: uma vez usando o operador de concatenação && e uma vez usando funções sql aninhadas.

Nota

O operador && ignora os espaços em branco à direita. Ele só mantém um espaço em branco no literal ' '.

Este exemplo ilustra o efeito das funções UPPER( ), LOWER( ) e INITCAP( ). Considerar a diferença entre as funções 'GmbH' no nome do agente de frete.

Este exemplo ilustra a utilização de funções de processamento de cadeia para extrair as informações do ano, do mês e do dia de um campo de data.

Nota

Considere que o formato interno para campos de data é AAAAMMDD. Os hífens na primeira coluna pertencem ao formato de saída para campos de data (formato ISO). Eles não estão presentes no formato interno. O formato interno fica visível após o lançamento do campo de data para o tipo CHAR( 8 ). Isso você pode ver na segunda coluna.

Testar: processamento de cadeia

  1. Crie uma nova classe global que implemente a interface IF_OO_ADT_CLASSRUN.
  2. Copie o seguinte snippet de código para a parte de implementação do método if_oo_adt_classrun~main( ):
    Code Snippet
    1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
    SELECT FROM /dmo/customer FIELDS customer_id, street && ',' && ' ' && postal_code && ' ' && city AS address_expr, concat( street, concat_with_space( ',', concat_with_space( postal_code, upper( city ), 1 ), 1 ) ) AS address_func WHERE country_code = 'ES' INTO TABLE @DATA(result_concat). out->write( EXPORTING data = result_concat name = 'RESULT_CONCAT' ). ********************************************************************** SELECT FROM /dmo/carrier FIELDS carrier_id, name, upper( name ) AS name_upper, lower( name ) AS name_lower, initcap( name ) AS name_initcap WHERE carrier_id = 'SR' INTO TABLE @DATA(result_transform). out->write( EXPORTING data = result_transform name = 'RESULT_TRANSLATE' ). ********************************************************************** SELECT FROM /dmo/flight FIELDS flight_date, cast( flight_date as char( 8 ) ) AS flight_date_raw, left( flight_Date, 4 ) AS year, right( flight_date, 2 ) AS day, substring( flight_date, 5, 2 ) AS month WHERE carrier_id = 'LH' AND connection_id = '0400' INTO TABLE @DATA(result_substring). out->write( EXPORTING data = result_substring name = 'RESULT_SUBSTRING' ).
  3. Selecione CTRL + F3 para ativar a classe e F9 para executá-la como um aplicativo de console.
  4. Analise a saída do console.
  5. Jogue com as expressões e funções nas listas FIELDS das instruções SELECT para se familiarizar com a sintaxe e a função.

Executar processamento de dados no banco de dados

Neste exercício, você envia o cálculo de assentos livres e a concatenação do ID da companhia aérea e do nome da companhia aérea para o banco de dados.

Modelo:

  • /LRN/CL_S4D401_DBS_NESTED_JOIN (classe global)

Solução:

  • /LRN/CL_S4D401_DBS_PUSH_DOWN (classe global)

Tarefa 1: Copiar modelo (opcional)

Copie a classe modelo /LRN/CL_S4D401_DBS_NESTED_JOIN. Se você tiver concluído o exercício anterior, pode ignorar esta tarefa e continuar processando sua classe ZCL_##_SOLUTION.

Etapas

  1. Copie a classe /LRN/CL_S4D401_DBS_NESTED_JOIN para uma classe em seu próprio pacote (nome sugerido: ZCL_##_SOLUTION, onde ## representa seu número de grupo).

    1. No Explorador de projetos, clique com o botão direito na classe /LRN/CL_S4D401_DBS_NESTED_JOIN para abrir o menu de contexto.

    2. No menu de contexto, selecione Duplicar....

    3. Insira o nome do seu pacote no campo Pacote. No campo Nome, insira ZCL_##_SOLUTION, em que ## representa seu número de grupo.

    4. Selecione Avançar.

    5. Confirme a ordem de transporte e selecione Concluir.

  2. Ative a cópia.

    1. Pressione Ctrl + F3 para ativar a classe.

Tarefa 2: Cálculo push-down

Na classe local LCL_PASSENGER_FLIGHT, amplie o tipo de linha do atributo estático flights_buffer com um componente seats_free. Ajuste a implementação do método GET_FLIGHTS_BY_CARRIER e adicione o cálculo de assentos livres à instrução SELECT. Em seguida, ajuste a implementação do método CONSTRUCTOR. Adicione o cálculo à instrução SELECT SINGLE e use o resultado do cálculo para preencher o atributo de instância seats_free.

Etapas

  1. Na classe local LCL_PASSENGER_FLIGHT, navegue para a definição do tipo de estrutura ST_FLIGHTS_BUFFER.

    1. Por exemplo, você pode abrir a guia Tipos locais no editor e procurar BEGIN OF st_flights_buffer.

    2. Como alternativa, você pode expandir ZCL_##_SOLUTIONLCL_PASSENGER_FLIGHT na visão Estrutura à esquerda e selecionar ST_FLIGHTS_BUFFER.

  2. Após o componente seats_ocupada, adicione um novo componente seats_free do mesmo tipo que o atributo de instância seats_free.

    1. Ajuste o código da seguinte forma:

      ABAP
      1234567891011
      TYPES: BEGIN OF st_flights_buffer, carrier_id TYPE /lrn/passflight-carrier_id, connection_id TYPE /lrn/passflight-connection_id, flight_date TYPE /lrn/passflight-flight_date, plane_type_id TYPE /lrn/passflight-plane_type_id, seats_max TYPE /lrn/passflight-seats_max, seats_occupied TYPE /lrn/passflight-seats_occupied, seats_free TYPE i, price TYPE /lrn/passflight-price, currency_code TYPE /lrn/passflight-currency_code, END OF st_flights_buffer.
  3. Navegue para a implementação do método GET_FLIGHTS_BY_CARRIER e adicione o cálculo dos assentos livres à lista de campos da instrução SELECT.

    Cuidado

    Certifique-se de que o cálculo está na mesma posição que o novo componente do tipo de estrutura ST_FLIGHTS_BUFFER. Como alternativa, você pode usar o suplemento CORRESPONDING FIELDS OF na cláusula INTO.
    1. Ajuste o código da seguinte forma:

      ABAP
      12345678
      SELECT FROM /lrn/passflight FIELDS carrier_id, connection_id, flight_date, plane_type_id, seats_max, seats_occupied, seats_max - seats_occupied AS seats_free, price, currency_code WHERE carrier_id = @i_carrier_id INTO TABLE @flights_buffer.
  4. Navegue para a implementação do método CONSTRUCTOR e adicione o cálculo dos assentos livres à lista de campos da instrução SELECT SINGLE.

    1. Ajuste o código da seguinte forma:

      ABAP
      12345678910
      SELECT SINGLE FROM /lrn/passflight FIELDS plane_type_id, seats_max, seats_occupied, seats_max - seats_occupied AS seats_free, price, currency_code WHERE carrier_id = @i_carrier_id AND connection_id = @i_connection_id AND flight_date = @i_flight_date INTO CORRESPONDING FIELDS OF @flight_raw.
  5. Role para baixo até a atribuição de valor ao atributo de instância seats_free. Substitua a expressão aritmética no lado direito do operador de atribuição pelo conteúdo de flight_raw-seats_free.

    1. Ajuste o código da seguinte forma:

      ABAP
      12345
      planetype = flight_raw-plane_type_id. seats_max = flight_raw-seats_max. seats_occ = flight_raw-seats_occupied. * seats_free = flight_raw-seats_max - flight_raw-seats_occupied. seats_free = flight_raw-seats_free.

Tarefa 3: Enviar para baixo a concatenação de cadeias

Na classe local LCL_CARRIER, ajuste a implementação do método CONSTRUCTOR. Mova a concatenação do ID da companhia aérea e o nome da companhia aérea para a lista de campos da instrução SELECT SINGLE e armazene o resultado no nome do atributo de instância.

Etapas

  1. Na classe local LCL_CARRIER, navegue para a implementação do método CONSTRUCTOR.

    1. Execute esta etapa como anteriormente.

  2. Localize a atribuição de valores para o atributo de nome. Analise-o e adicione um sinal de comentário no início da linha de código.

    1. Rolar para baixo até a instrução name = carrier_id && ` ` && name.

    2. Posicione o cursor em qualquer lugar nessa linha de código e pressione Ctrl + <.

  3. Na lista de campos da instrução SELECT SINGLE, substitua o campo de tabela de banco de dados NAME por uma chamada de uma função de processamento de cadeia adequada para concatenar o ID e o nome da companhia aérea separados por um único espaço.

    Nota

    Como alternativa, você pode utilizar carrier_id && ' ' && name na lista de campos da instrução SELECT SINGLE.
    1. Ajuste o código da seguinte forma:

      ABAP
      123456
      SELECT SINGLE FROM /lrn/carrier * FIELDS name, currency_code FIELDS concat_with_space( carrier_id, name, 1 ), currency_code WHERE carrier_id = @i_carrier_id INTO ( @me->name, @me->currency_code ).
  4. Ative e teste sua classe global como aplicativo de console.

    1. Pressione Ctrl + F3.

    2. Pressione F9.