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 tablaSELECT * 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 inlineSELECT 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 kunnr7. 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 ExpressionSELECT 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ónSELECT * 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_date10. View parametrizado en ABAP
" Pasar parámetrosSELECT * FROM z_i_ordersbydate( p_from_date = '20240101', p_to_date = '20241231' ) INTO TABLE @DATA(lt_orders_2024).
" Con variablesDATA: 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
| Tipo | Prefijo | Propósito |
|---|---|---|
| Interface View | I_ o Z_I_ | Modelo de datos base, reutilizable |
| Consumption View | C_ o Z_C_ | Específico para UI, con anotaciones UI |
| Basic View | R_ o Z_R_ | Restringido, para uso interno |
| Extension View | E_ 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 cadenaconcat( field1, field2 )substring( field, position, length )length( field )upper( field )lower( field )ltrim( field, char )rtrim( field, char )
// Funciones numéricasabs( field )ceil( field )floor( field )round( field, decimals )div( field1, field2 )mod( field1, field2 )
// Funciones de fecha/horadats_days_between( date1, date2 )dats_add_days( date, days )dats_add_months( date, months )$session.system_date$session.user$session.client
// Conversionescast( field as type )currency_conversion( ... )unit_conversion( ... )
// Manejo de nuloscoalesce( 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 asociacionesassociation [1..1] to ... // Exactamente unaassociation [0..1] to ... // Cero o unaassociation [0..*] to ... // Cero a muchasassociation [1..*] to ... // Una a muchasNotas 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.authorizationCheckpara 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.