Implementar expressões SQL em visões CDS

Objectives

After completing this lesson, you will be able to:
  • Motive o uso do pushdown de código em visões CDS.
  • Use expressões SQL em visões CDS.

Pushdown de código no ABAP SQL e ABAP CDS

Em uma parte anterior desta jornada de aprendizagem, você aprendeu que, com os enormes recursos de análise de dados do SAP HANA, é recomendável que você faça cálculos já no banco de dados sempre que possível. Você também aprendeu que o ABAP SQL oferece muitas expressões e funções integradas para esse fim.

A maioria dessas expressões e funções integradas também estão disponíveis em definições de visão CDS. Isso permite que você mova os cálculos complicados para uma definição de visão CDS e, em seguida, recupere os dados da visão CDS.

Vejamos um exemplo. Nesse código ABAP, a instrução ABAP SQL usa uma expressão aritmética para calcular o número de assentos livres em um voo, subtraindo o número de assentos ocupados do número total de assentos.

Neste exemplo seguinte, a expressão aritmética é deslocada para uma definição de visão CDS. O resultado do cálculo é visível para consumidores da visão como elemento de visão seats_free. O código ABAP lê o elemento de visão seats_free como qualquer outro elemento de visão.

Nota

Para o consumidor de uma visão CDS, não faz diferença se um elemento de visão for simplesmente uma projeção de um campo de tabela de banco de dados ou o resultado de um cálculo complicado.

Mover a lógica SQL do ABAP SQL para uma visão CDS tem várias vantagens:

Encapsulamento

Como a lógica SQL está oculta na definição da visão CDS, as instruções ABAP SQL se tornam mais fáceis de ler.

Reutilizar

Ao ler a partir da mesma visão CDS, você pode reutilizar facilmente a lógica SQL em outras aplicações. Em particular, você pode usar a lógica SQL nos frameworks que usam visões CDS, por exemplo, funções analíticas integradas, extratores de dados baseados em CDS para SAP BW, programação de aplicativos ABAP RESTful e muito mais.

Semântica

Você pode adicionar semântica ao resultado do cálculo, atribuindo um nome significativo ao elemento e anotando-o com anotações de elemento.

Regras de autorização

Você pode restringir o acesso aos dados calculados criando um controle de acesso CDS para a visão CDS.

Literais no CDS do ABAP

Ao comparar literais no ABAP SQL e literais no ABAP CDS, você notará que o ABAP CDS oferece uma variedade maior de tipos.

Literais de caracteres

Enquanto o ABAP SQL só conhece literais de caracteres do tipo predefinido C (correspondente ao tipo de dicionário CHAR), o ABAP CDS usa o tipo de dicionário predefinido NUMC, quando o literal de caracteres é composto somente por dígitos.

Literais numéricos

O ABAP SQL só conhece literais de números inteiros positivos e negativos e usa o tipo I do ABAP predefinido (tipo de dicionário INT4) para todos eles.

Por outro lado, o ABAP CDS também usa os tipos de dicionário INT4, INT2 e INT1, selecionando o tipo mais curto que pode conter o valor do literal. O valor literal 255, por exemplo, ainda é do tipo INT1, enquanto 256 é demasiado grande para um byte e requer o tipo INT2.

O CDS do ABAP também conhece literais não inteiros. Eles contêm um ponto decimal e têm o tipo de dicionário predefinido FLTP.

Nota

Não há suporte a literais não inteiros no ABAP SQL –- principalmente porque o sinal do período (.) está reservado como delimitador de instrução.

Conversões de tipo

Como o ABAP SQL, você pode usar a expressão CAST para implementar conversões de tipo técnico.

O operando para a expressão cast não pode ser apenas um literal, como em nosso exemplo. Todos os tipos de outras expressões são possíveis, por exemplo, campos da fonte de dados, expressões aritméticas, distinções CASE, funções SQL, etc.

O tipo de destino pode ser especificado como um tipo de dicionário predefinido. Isso é idêntico ao uso de CAST no ABAP SQL. Contudo, considere que no CDS é necessário um prefixo abap..

existem restrições a respeito da combinação de tipo de fonte e tipo de objetivo. Algumas combinações não são suportadas. Outras só funcionam com limitações. Por exemplo, não é possível atualmente utilizar operandos do tipo FLTP como fonte da expressão CAST. Uma matriz detalhada pode ser encontrada na documentação de linguagem ABAP.

É uma especialidade do CAST no ABAP CDS que você também pode utilizar um elemento de dados Dictionary como tipo de destino. Este tipo de cast não só converte o tipo técnico. Ele também obtém informações semânticas como os denominadores de campo do elemento de dados.

Um cast com um elemento de dados como tipo de destino pode até ser útil se o tipo técnico do operando e o elemento de dados de destino forem idênticos. Neste caso, só são modificadas as informações semânticas do operando. Se um cast não modificar o tipo técnico, a verificação de sintaxe emite uma advertência. Você pode suprimir esse aviso com o suplemento PRESERVING TYPE dentro da expressão cast.

Distinções de caso no CDS do ABAP

O CDS do ABAP oferece exatamente as mesmas distinções CASE que o ABAP SQL. Diferenças de casos simples e complexas seguem as mesmas regras de sintaxe e têm a mesma funcionalidade.

Isso pode ser ilustrado com um exemplo. A expressão de caso simples à esquerda vem de uma instrução SELECT do ABAP SQL. A expressão de caso simples à direita faz parte de uma definição de entidade de visão CDS. Não há diferença - além da formatação e coloração diferentes nos dois editores.

Expressões aritméticas no CDS do ABAP

Como o ABAP SQL, as expressões aritméticas podem ser usadas na lista de elementos de uma definição de visão CDS. As mesmas regras e restrições se aplicam aos dois casos. Como no ABAP SQL, a restrição mais importante é que o operador de divisão (/) só é permitido em expressões de ponto flutuante.

Dica

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

Compare esses exemplos do ABAP SQL e do ABAP CDS. Novamente, a diferença é principalmente a formatação. Existem duas diferenças que não estão realmente relacionadas às expressões aritméticas, mas sim ao uso de literais e expressões cast:

  • A expressão cast no ABAP CDS requer o prefixo "abap" antes dos tipos de dicionário predefinidos.
  • Você pode usar literais de ponto flutuante no CDS do ABAP. Você pode utilizar o literal 100.0 diretamente na expressão de ponto flutuante. Não é necessário usar literal inteiro 100 e lançá-lo para o tipo predefinido FLTP.

Utilizar expressões em uma Visão CDS

Você quer ampliar sua entidade de visão CDS com lógica SQL. Em uma primeira etapa, você marca empregados como chefes de departamento e assistentes e calcula o salário mensal.

Modelo:

  • /LRN/C_EMPLOYEE_QRY (Definição de dados)

Solução:

  • /LRN/C_EMPLOYEE_EXP (Definição de dados)

Pré-requisitos

Para este exercício, você precisa da entidade de visão CDS que criou em um exercício anterior (o nome sugerido foi: Z##_C_EmployeeQuery, em que ## é o número do seu grupo). Se você não concluiu esse exercício, crie uma cópia da definição de dados /LRN/C_EMPLOYEE_QRY.

Tarefa 1: Utilizar distinção CASE

Em sua entidade de visão CDS para avaliar dados do empregado (o nome sugerido era: Z##_C_EmployeeQuery, onde ## é o número do seu grupo), defina um novo elemento de visão (nome do elemento sugerido: EmployeeRole). Defina o valor de retorno de elemento 'H' se o empregado for o chefe de departamento, o valor ' A' se o empregado for o assistente de departamento e ' ' para todos os outros empregados.

Etapas

  1. Na lista de elementos de sua entidade de visão, antes da associação exposta, adicione uma distinção de casos que compara o valor de EmployeeID com o valor do elemento HeadID no destino da associação _Department. Se os valores forem idênticos, o valor de retorno é 'H'.

    1. Ajuste o código da seguinte forma:

      Code Snippet
      12345678910111213141516
      define view entity Z##_C_EmployeeQuery as select from Z##_R_Employee { key EmployeeId, FirstName, LastName, DepartmentId, _Department.Description as DepartmentDescription, _Department._Assistant.LastName as AssistantName, case EmployeeId when _Department.HeadId then 'H'
  2. Adicione uma segunda ramificação que compare o valor de EmployeeID com o valor do elemento AssistantID no destino da associação _Department. Se os valores forem idênticos, o valor de retorno é 'A'.

    1. Ajuste o código da seguinte forma:

      Code Snippet
      123456
      case EmployeeId when _Department.HeadId then 'H' when _Department.AssistantId then 'A'
  3. Adicione uma ramificação else para retornar o valor ' '.

    1. Ajuste o código da seguinte forma:

      Code Snippet
      1234567
      case EmployeeId when _Department.HeadId then 'H' when _Department.AssistantId then 'A' else ' '
  4. Feche a expressão CASE e especifique um nome de elemento (nome do elemento sugerido: EmployeeRole).

    1. Ajuste o código da seguinte forma:

      Code Snippet
      12345678
      case EmployeeId when _Department.HeadId then 'H' when _Department.AssistantId then 'A' else ' ' end as EmployeeRole,
  5. Adicione a anotação necessária para definir uma etiqueta para o campo calculado (valor sugerido: Função do empregado).

    1. Ajuste o código da seguinte forma:

      Code Snippet
      123456789
      @EndUserText.label: 'Employee Role' case EmployeeId when _Department.HeadId then 'H' when _Department.AssistantId then 'A' else ' ' end as EmployeeRole,

Tarefa 2: Utilizar expressão aritmética

Com base no salário anual do empregado, calcule o salário mensal (nome do elemento sugerido: MonthlySalary).

Etapas

  1. Use uma expressão aritmética com o operador / para dividir o conteúdo de AnnualSalary por 12.

    1. Ajuste o código da seguinte forma:

      Code Snippet
      1234567891011
      @EndUserText.label: 'Employee Role' case EmployeeId when _Department.HeadId then 'H' when _Department.AssistantId then 'A' else ' ' end as EmployeeRole, cast( AnnualSalary as abap.fltp ) / 12.0 as MonthlySalary,
  2. Adicione a anotação necessária para definir um rótulo para o campo calculado (valor sugerido: Salário mensal).

    1. Ajuste o código da seguinte forma:

      Code Snippet
      123456789101112
      @EndUserText.label: 'Employee Role' case EmployeeId when _Department.HeadId then 'H' when _Department.AssistantId then 'A' else ' ' end as EmployeeRole, @EndUserText.label: 'Monthly Salary' cast( AnnualSalary as abap.fltp ) / 12.0 as MonthlySalary,
  3. Adicione o elemento CurrencyCode à lista de elementos e use a anotação @Semantics.amount.currencyCode para vinculá-lo ao elemento MonthlySalary.

    1. Ajuste o código da seguinte forma:

      Code Snippet
      12345678
      @EndUserText.label: 'Monthly Salary' @Semantics.amount.currencyCode: 'CurrencyCode' cast( AnnualSalary as abap.fltp ) / 12.0 as MonthlySalary, CurrencyCode,
  4. Ative a definição de dados CDS.

    1. Pressione Ctrl + F3 para ativar o objeto de desenvolvimento.

  5. Abra a Visualização de dados e analise a saída.

    1. Pressione F8 para abrir a Visualização de dados.