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
- Crie uma nova classe global que implemente a interface IF_OO_ADT_CLASSRUN.
- Copie o seguinte snippet de código para a parte de implementação do método if_oo_adt_classrun~main( ):
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'
).
- Selecione CTRL + F3 para ativar a classe e F9 para executá-la como um aplicativo de console.
- Analise a saída do console.
- 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
- Crie uma nova classe global que implemente a interface IF_OO_ADT_CLASSRUN.
- Copie o seguinte snippet de código para a parte de implementação do método if_oo_adt_classrun~main( ):
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'
).
- Selecione CTRL + F3 para ativar a classe e F9 para executá-la como um aplicativo de console.
- Analise a saída do console.
- Posicione o cursor em uma das funções numéricas (por exemplo, setor de atividade e selecione F1 para abrir a documentação.
- 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
- Crie uma nova classe global que implemente a interface IF_OO_ADT_CLASSRUN.
- Copie o seguinte snippet de código para a parte de implementação do método if_oo_adt_classrun~main( ):
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'
).
- Selecione CTRL + F3 para ativar a classe e F9 para executá-la como um aplicativo de console.
- Analise a saída do console.
- 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.
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
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).
No Explorador de projetos, clique com o botão direito na classe /LRN/CL_S4D401_DBS_NESTED_JOIN para abrir o menu de contexto.
No menu de contexto, selecione Duplicar....
Insira o nome do seu pacote no campo Pacote. No campo Nome, insira ZCL_##_SOLUTION, em que ## representa seu número de grupo.
Selecione Avançar.
Confirme a ordem de transporte e selecione Concluir.
Ative a cópia.
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
Na classe local LCL_PASSENGER_FLIGHT, navegue para a definição do tipo de estrutura ST_FLIGHTS_BUFFER.
Por exemplo, você pode abrir a guia Tipos locais no editor e procurar BEGIN OF st_flights_buffer.
Como alternativa, você pode expandir ZCL_##_SOLUTION→LCL_PASSENGER_FLIGHT na visão Estrutura à esquerda e selecionar ST_FLIGHTS_BUFFER.
Após o componente seats_ocupada, adicione um novo componente seats_free do mesmo tipo que o atributo de instância seats_free.
Ajuste o código da seguinte forma:
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.
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.
Ajuste o código da seguinte forma:
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.
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.
Ajuste o código da seguinte forma:
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.
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.
Ajuste o código da seguinte forma:
12345
planetype = flight_raw-plane_type_id.
seats_max = flight_raw-seats_max.
seats_occ = 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
Na classe local LCL_CARRIER, navegue para a implementação do método CONSTRUCTOR.
Execute esta etapa como anteriormente.
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.
Rolar para baixo até a instrução name = carrier_id && ` ` && name.
Posicione o cursor em qualquer lugar nessa linha de código e pressione Ctrl + <.
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.
Ajuste o código da seguinte forma:
123456
SELECT SINGLE
FROM /lrn/carrier
FIELDS concat_with_space( carrier_id, name, 1 ), currency_code
WHERE carrier_id = @i_carrier_id
INTO ( @me->name, @me->currency_code ).
Ative e teste sua classe global como aplicativo de console.
Pressione Ctrl + F3.
Pressione F9.