CDS Views (Core Data Services) sind die moderne Art, Datenmodelle in SAP zu definieren. Sie ermöglichen semantisch reiche, wiederverwendbare Datendefinitionen direkt auf Datenbankebene mit Push-Down-Optimierung für HANA.
Was sind CDS Views?
CDS Views sind:
- Deklarative SQL-Erweiterungen für semantische Datenmodellierung
- Datenbankviews mit erweiterten Funktionen (Annotationen, Assoziationen)
- Grundlage für SAP Fiori, RAP und moderne SAP-Entwicklung
- Performant durch Push-Down auf die Datenbank (HANA)
Grundlegende Syntax
@AbapCatalog.sqlViewName: 'ZSQL_VIEW_NAME'@AbapCatalog.compiler.compareFilter: true@AccessControl.authorizationCheck: #CHECK@EndUserText.label: 'Beschreibung der View'
define view Z_CDS_VIEW_NAME as select from <datenquelle> { <feldliste> }Beispiele
1. Einfache CDS View
@AbapCatalog.sqlViewName: 'ZSQLCUSTOMERS'@AbapCatalog.compiler.compareFilter: true@AccessControl.authorizationCheck: #NOT_REQUIRED@EndUserText.label: 'Kundenstammdaten'
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. CDS View in ABAP verwenden
" CDS View wie eine Tabelle verwendenSELECT * 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.
" Mit Inline-DeklarationSELECT customerid, customername, city FROM z_i_customers WHERE country = 'DE' INTO TABLE @DATA(lt_german_customers).3. CDS View mit JOIN
@AbapCatalog.sqlViewName: 'ZSQLORDERCUST'@AccessControl.authorizationCheck: #NOT_REQUIRED@EndUserText.label: 'Bestellungen mit Kundendaten'
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. Berechnete Felder (Calculated Fields)
@AbapCatalog.sqlViewName: 'ZSQLORDERCALC'@AccessControl.authorizationCheck: #NOT_REQUIRED@EndUserText.label: 'Bestellungen mit Berechnungen'
define view Z_I_OrderCalculations as select from vbak{ key vbeln as OrderNumber, netwr as NetValue, waerk as Currency,
// Berechnungen netwr * 1.19 as GrossValue,
// Bedingungen mit CASE case when netwr >= 10000 then 'HIGH' when netwr >= 1000 then 'MEDIUM' else 'LOW' end as ValueCategory,
// Datumsfunktionen dats_days_between( erdat, $session.system_date ) as DaysSinceOrder}6. Aggregationen
@AbapCatalog.sqlViewName: 'ZSQLCUSTTOTAL'@AccessControl.authorizationCheck: #NOT_REQUIRED@EndUserText.label: 'Kundenumsätze aggregiert'
define view Z_I_CustomerTotals as select from vbak{ key kunnr as CustomerId,
// Aggregatfunktionen sum( netwr ) as TotalOrderValue, count(*) as OrderCount, avg( netwr ) as AverageOrderValue, min( erdat ) as FirstOrderDate, max( erdat ) as LastOrderDate}group by kunnr7. Assoziationen (Associations)
@AbapCatalog.sqlViewName: 'ZSQLORDERASSOC'@AccessControl.authorizationCheck: #NOT_REQUIRED@EndUserText.label: 'Bestellungen mit Assoziationen'
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,
// Assoziationen exponieren _Customer, _Items}8. Assoziationen in ABAP nutzen
" Path Expression nutzenSELECT OrderNumber, OrderDate, NetValue, \_Customer-name1 as CustomerName, \_Customer-ort01 as CustomerCity FROM z_i_orders INTO TABLE @DATA(lt_orders_with_customer).
" Mit WHERE auf AssoziationSELECT * FROM z_i_orders WHERE \_Customer-land1 = 'DE' INTO TABLE @DATA(lt_german_orders).9. Parameter in CDS Views
@AbapCatalog.sqlViewName: 'ZSQLORDERPARAM'@AccessControl.authorizationCheck: #NOT_REQUIRED@EndUserText.label: 'Bestellungen mit Parameter'
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. Parametrisierte View in ABAP
" Parameter übergebenSELECT * FROM z_i_ordersbydate( p_from_date = '20240101', p_to_date = '20241231' ) INTO TABLE @DATA(lt_orders_2024).
" Mit VariablenDATA: 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. Annotationen für UI (Fiori)
@AbapCatalog.sqlViewName: 'ZSQLCUSTUI'@AccessControl.authorizationCheck: #CHECK@EndUserText.label: 'Kunden für UI'
@UI.headerInfo: { typeName: 'Kunde', typeNamePlural: 'Kunden', 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: 'Zugriffskontrolle für Kunden'@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 und 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: 'Erweiterung für Kunden'
extend view Z_I_Customers with Z_E_Customers_Extension{ // Zusätzliche Felder aus anderen Tabellen kna1.brsch as Industry, kna1.kukla as CustomerClass}CDS View Typen
| Typ | Präfix | Zweck |
|---|---|---|
| Interface View | I_ oder Z_I_ | Basis-Datenmodell, wiederverwendbar |
| Consumption View | C_ oder Z_C_ | UI-spezifisch, mit UI-Annotationen |
| Basic View | R_ oder Z_R_ | Restricted, für interne Nutzung |
| Extension View | E_ oder Z_E_ | Erweiterungen bestehender Views |
Wichtige Annotationen
// Katalog-Annotationen@AbapCatalog.sqlViewName: 'SQL_NAME' // SQL View Name (max 16 Zeichen)@AbapCatalog.compiler.compareFilter: true // Filteroptimierung@AbapCatalog.preserveKey: true // Schlüssel erhalten@AbapCatalog.buffering.status: #ACTIVE // Pufferung aktivieren
// Zugriffskontrolle@AccessControl.authorizationCheck: #CHECK // Berechtigungsprüfung@AccessControl.authorizationCheck: #NOT_REQUIRED
// Metadaten@EndUserText.label: 'Beschreibung'@ObjectModel.representativeKey: 'FieldName'@ObjectModel.semanticKey: ['Field1', 'Field2']
// Analytics@Analytics.dataCategory: #CUBE@Analytics.dataCategory: #DIMENSION
// OData/Fiori@OData.publish: true@UI.headerInfo.typeName: 'Entity'CDS Funktionen
// String-Funktionenconcat( field1, field2 )substring( field, position, length )length( field )upper( field )lower( field )ltrim( field, char )rtrim( field, char )
// Numerische Funktionenabs( field )ceil( field )floor( field )round( field, decimals )div( field1, field2 )mod( field1, field2 )
// Datums-/Zeitfunktionendats_days_between( date1, date2 )dats_add_days( date, days )dats_add_months( date, months )$session.system_date$session.user$session.client
// Konvertierungencast( field as type )currency_conversion( ... )unit_conversion( ... )
// Null-Behandlungcoalesce( field, default )Best Practices
// 1. Sinnvolle Feldnamen (CamelCase)@AbapCatalog.sqlViewName: 'ZSQLSALES'define view Z_I_SalesOrders as select from vbak{ key vbeln as SalesOrderId, // Nicht: VBELN kunnr as CustomerId, // Nicht: KUNNR erdat as CreationDate // Nicht: ERDAT}
// 2. Annotationen für Semantik{ @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. Kardinalitäten bei Assoziationenassociation [1..1] to ... // Genau eineassociation [0..1] to ... // Null oder eineassociation [0..*] to ... // Null bis vieleassociation [1..*] to ... // Eine bis vieleWichtige Hinweise / Best Practice
- CDS Views sind die Grundlage für moderne SAP-Entwicklung (Fiori, RAP).
- Nutzen Sie Interface Views (
I_) für wiederverwendbare Basismodelle. - Nutzen Sie Consumption Views (
C_) für UI-spezifische Anforderungen. - Assoziationen statt JOINs für flexiblere, performantere Abfragen.
- Annotationen steuern Verhalten, UI und Berechtigungen.
@AccessControl.authorizationCheckfür Berechtigungsprüfung aktivieren.- CDS Views können in ABAP wie normale Tabellen in
SELECTverwendet werden. - HANA-Optimierung: Berechnungen werden auf die Datenbank gepusht.
- Verwenden Sie Parameter für flexible, wiederverwendbare Views.
- Virtual Data Model (VDM): Folgen Sie SAP-Namenskonventionen für konsistente Modelle.