CDS Views en ABAP: Entender y usar Core Data Services

Kategorie
ABAP-Statements
Veröffentlicht
Autor
Johannes

CDS Views (Core Data Services) son la forma moderna de definir modelos de datos en SAP. Permiten definiciones de datos semánticamente ricas y reutilizables directamente a nivel de base de datos con optimización push-down para HANA.

¿Qué son los CDS Views?

Los CDS Views son:

  • Extensiones SQL declarativas para modelado semántico de datos
  • Vistas de base de datos con funciones extendidas (anotaciones, asociaciones)
  • Fundamento para SAP Fiori, RAP y desarrollo SAP moderno
  • Eficientes mediante push-down a la base de datos (HANA)

Sintaxis básica

@AbapCatalog.sqlViewName: 'ZSQL_VIEW_NAME'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Descripción del view'
define view Z_CDS_VIEW_NAME
as select from <fuente_datos>
{
<lista_campos>
}

Ejemplos

1. CDS View simple

@AbapCatalog.sqlViewName: 'ZSQLCUSTOMERS'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Datos maestros de clientes'
define view Z_I_Customers
as select from kna1
{
key kunnr as CustomerId,
name1 as CustomerName,
ort01 as City,
land1 as Country,
erdat as CreatedDate
}

2. Usar CDS View en ABAP

" Usar CDS View como una tabla
SELECT * FROM z_i_customers
INTO TABLE @DATA(lt_customers)
WHERE country = 'DE'.
LOOP AT lt_customers INTO DATA(ls_customer).
WRITE: / ls_customer-customerid, ls_customer-customername.
ENDLOOP.
" Con declaración inline
SELECT customerid, customername, city
FROM z_i_customers
WHERE country = 'DE'
INTO TABLE @DATA(lt_german_customers).

3. CDS View con JOIN

@AbapCatalog.sqlViewName: 'ZSQLORDERCUST'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Pedidos con datos de cliente'
define view Z_I_OrdersWithCustomer
as select from vbak as order
inner join kna1 as customer
on order.kunnr = customer.kunnr
{
key order.vbeln as OrderNumber,
order.erdat as OrderDate,
order.netwr as NetValue,
order.waerk as Currency,
customer.kunnr as CustomerId,
customer.name1 as CustomerName,
customer.ort01 as CustomerCity
}

4. LEFT OUTER JOIN

define view Z_I_CustomersWithOrders
as select from kna1 as customer
left outer join vbak as order
on customer.kunnr = order.kunnr
{
key customer.kunnr as CustomerId,
customer.name1 as CustomerName,
order.vbeln as OrderNumber,
order.netwr as OrderValue
}

5. Campos calculados (Calculated Fields)

@AbapCatalog.sqlViewName: 'ZSQLORDERCALC'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Pedidos con cálculos'
define view Z_I_OrderCalculations
as select from vbak
{
key vbeln as OrderNumber,
netwr as NetValue,
waerk as Currency,
// Cálculos
netwr * 1.19 as GrossValue,
// Condiciones con CASE
case
when netwr >= 10000 then 'HIGH'
when netwr >= 1000 then 'MEDIUM'
else 'LOW'
end as ValueCategory,
// Funciones de fecha
dats_days_between( erdat, $session.system_date ) as DaysSinceOrder
}

6. Agregaciones

@AbapCatalog.sqlViewName: 'ZSQLCUSTTOTAL'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Ventas de clientes agregadas'
define view Z_I_CustomerTotals
as select from vbak
{
key kunnr as CustomerId,
// Funciones de agregación
sum( netwr ) as TotalOrderValue,
count(*) as OrderCount,
avg( netwr ) as AverageOrderValue,
min( erdat ) as FirstOrderDate,
max( erdat ) as LastOrderDate
}
group by kunnr

7. Asociaciones (Associations)

@AbapCatalog.sqlViewName: 'ZSQLORDERASSOC'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Pedidos con asociaciones'
define view Z_I_Orders
as select from vbak as Order
association [1..1] to kna1 as _Customer
on $projection.CustomerId = _Customer.kunnr
association [0..*] to vbap as _Items
on $projection.OrderNumber = _Items.vbeln
{
key vbeln as OrderNumber,
kunnr as CustomerId,
erdat as OrderDate,
netwr as NetValue,
// Exponer asociaciones
_Customer,
_Items
}

8. Usar asociaciones en ABAP

" Usar Path Expression
SELECT OrderNumber,
OrderDate,
NetValue,
\_Customer-name1 as CustomerName,
\_Customer-ort01 as CustomerCity
FROM z_i_orders
INTO TABLE @DATA(lt_orders_with_customer).
" Con WHERE sobre asociación
SELECT *
FROM z_i_orders
WHERE \_Customer-land1 = 'DE'
INTO TABLE @DATA(lt_german_orders).

9. Parámetros en CDS Views

@AbapCatalog.sqlViewName: 'ZSQLORDERPARAM'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Pedidos con parámetro'
define view Z_I_OrdersByDate
with parameters
p_from_date : abap.dats,
p_to_date : abap.dats
as select from vbak
{
key vbeln as OrderNumber,
erdat as OrderDate,
netwr as NetValue,
kunnr as CustomerId
}
where erdat >= $parameters.p_from_date
and erdat <= $parameters.p_to_date

10. View parametrizado en ABAP

" Pasar parámetros
SELECT *
FROM z_i_ordersbydate( p_from_date = '20240101',
p_to_date = '20241231' )
INTO TABLE @DATA(lt_orders_2024).
" Con variables
DATA: lv_from TYPE d VALUE '20240101',
lv_to TYPE d VALUE '20241231'.
SELECT *
FROM z_i_ordersbydate( p_from_date = @lv_from,
p_to_date = @lv_to )
INTO TABLE @DATA(lt_orders).

11. Anotaciones para UI (Fiori)

@AbapCatalog.sqlViewName: 'ZSQLCUSTUI'
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Clientes para UI'
@UI.headerInfo: {
typeName: 'Cliente',
typeNamePlural: 'Clientes',
title: { value: 'CustomerName' }
}
define view Z_C_Customers
as select from z_i_customers
{
@UI.facet: [{ position: 10, type: #IDENTIFICATION_REFERENCE }]
key @UI.lineItem: [{ position: 10 }]
@UI.identification: [{ position: 10 }]
CustomerId,
@UI.lineItem: [{ position: 20 }]
@UI.identification: [{ position: 20 }]
@UI.selectionField: [{ position: 10 }]
CustomerName,
@UI.lineItem: [{ position: 30 }]
@UI.selectionField: [{ position: 20 }]
City,
@UI.lineItem: [{ position: 40 }]
Country
}

12. Access Control (DCL)

@EndUserText.label: 'Control de acceso para clientes'
@MappingRole: true
define role Z_I_Customers_Role {
grant select on Z_I_Customers
where Country = aspect pfcg_auth( ZAUTH_OBJ, ZLAND, ACTVT = '03' );
}

13. UNION y UNION ALL

define view Z_I_AllPartners
as select from kna1
{
key kunnr as PartnerId,
name1 as PartnerName,
'CUSTOMER' as PartnerType
}
union all
select from lfa1
{
key lifnr as PartnerId,
name1 as PartnerName,
'SUPPLIER' as PartnerType
}

14. CDS Table Functions (AMDP)

@EndUserText.label: 'CDS Table Function'
define table function Z_TF_ComplexLogic
with parameters
p_date : abap.dats
returns {
key OrderId : abap.char(10);
Amount : abap.curr(15,2);
Status : abap.char(1);
}
implemented by method
zcl_complex_logic=>get_orders;
CLASS zcl_complex_logic DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES if_amdp_marker_hdb.
CLASS-METHODS get_orders
FOR TABLE FUNCTION z_tf_complexlogic.
ENDCLASS.
CLASS zcl_complex_logic IMPLEMENTATION.
METHOD get_orders BY DATABASE FUNCTION FOR HDB
LANGUAGE SQLSCRIPT OPTIONS READ-ONLY
USING vbak.
RETURN SELECT vbeln as orderid,
netwr as amount,
'A' as status
FROM vbak
WHERE erdat = :p_date;
ENDMETHOD.
ENDCLASS.

15. Extend Views

@AbapCatalog.sqlViewAppendName: 'ZSQLCUSTEXT'
@EndUserText.label: 'Extensión para clientes'
extend view Z_I_Customers with Z_E_Customers_Extension
{
// Campos adicionales de otras tablas
kna1.brsch as Industry,
kna1.kukla as CustomerClass
}

Tipos de CDS View

TipoPrefijoPropósito
Interface ViewI_ o Z_I_Modelo de datos base, reutilizable
Consumption ViewC_ o Z_C_Específico para UI, con anotaciones UI
Basic ViewR_ o Z_R_Restringido, para uso interno
Extension ViewE_ o Z_E_Extensiones de views existentes

Anotaciones importantes

// Anotaciones de catálogo
@AbapCatalog.sqlViewName: 'SQL_NAME' // Nombre SQL View (máx 16 caracteres)
@AbapCatalog.compiler.compareFilter: true // Optimización de filtros
@AbapCatalog.preserveKey: true // Conservar clave
@AbapCatalog.buffering.status: #ACTIVE // Activar buffering
// Control de acceso
@AccessControl.authorizationCheck: #CHECK // Verificación de permisos
@AccessControl.authorizationCheck: #NOT_REQUIRED
// Metadatos
@EndUserText.label: 'Descripción'
@ObjectModel.representativeKey: 'FieldName'
@ObjectModel.semanticKey: ['Field1', 'Field2']
// Analytics
@Analytics.dataCategory: #CUBE
@Analytics.dataCategory: #DIMENSION
// OData/Fiori
@OData.publish: true
@UI.headerInfo.typeName: 'Entity'

Funciones CDS

// Funciones de cadena
concat( field1, field2 )
substring( field, position, length )
length( field )
upper( field )
lower( field )
ltrim( field, char )
rtrim( field, char )
// Funciones numéricas
abs( field )
ceil( field )
floor( field )
round( field, decimals )
div( field1, field2 )
mod( field1, field2 )
// Funciones de fecha/hora
dats_days_between( date1, date2 )
dats_add_days( date, days )
dats_add_months( date, months )
$session.system_date
$session.user
$session.client
// Conversiones
cast( field as type )
currency_conversion( ... )
unit_conversion( ... )
// Manejo de nulos
coalesce( field, default )

Mejores prácticas

// 1. Nombres de campo descriptivos (CamelCase)
@AbapCatalog.sqlViewName: 'ZSQLSALES'
define view Z_I_SalesOrders
as select from vbak
{
key vbeln as SalesOrderId, // No: VBELN
kunnr as CustomerId, // No: KUNNR
erdat as CreationDate // No: ERDAT
}
// 2. Anotaciones para semántica
{
@Semantics.amount.currencyCode: 'Currency'
netwr as NetAmount,
@Semantics.currencyCode: true
waerk as Currency,
@Semantics.quantity.unitOfMeasure: 'Unit'
kwmeng as Quantity,
@Semantics.unitOfMeasure: true
vrkme as Unit
}
// 3. Cardinalidades en asociaciones
association [1..1] to ... // Exactamente una
association [0..1] to ... // Cero o una
association [0..*] to ... // Cero a muchas
association [1..*] to ... // Una a muchas

Notas importantes / Mejores prácticas

  • Los CDS Views son el fundamento del desarrollo SAP moderno (Fiori, RAP).
  • Usa Interface Views (I_) para modelos base reutilizables.
  • Usa Consumption Views (C_) para requisitos específicos de UI.
  • Associations en lugar de JOINs para consultas más flexibles y eficientes.
  • Las anotaciones controlan comportamiento, UI y permisos.
  • Activa @AccessControl.authorizationCheck para verificación de permisos.
  • Los CDS Views pueden usarse en ABAP como tablas normales en SELECT.
  • Optimización HANA: Los cálculos se empujan a la base de datos.
  • Usa parámetros para views flexibles y reutilizables.
  • Virtual Data Model (VDM): Sigue las convenciones de nombres de SAP para modelos consistentes.