Emre Göçmen Blog

Getting Started with SAP ABAP Core Data Services (CDS)

5 min. read
2508 views
0 comments

Emre Göçmen

Author

Getting Started with SAP ABAP Core Data Services (CDS)

ABAP Core Data Services (CDS) - Comprehensive Guide

Table of Contents

  1. What is CDS?
  2. Advantages of ABAP CDS
  3. Creating CDS Views
  4. CDS Associations
  5. Creating OData Service with CDS
  6. CDS Analytical Queries
  7. Performance Optimization
  8. Conclusion

1. What is CDS?

Core Data Services (CDS) is a powerful framework developed by SAP for data modeling and data access that leverages the capabilities of SAP HANA. CDS extends traditional SQL VIEWs to allow for richer semantic modeling.

CDS is one of the foundational building blocks of SAP S/4HANA architecture and is used for:

  • Data modeling
  • Data access
  • Integration of business logic into data models
  • User Interface (UI) bindings
  • Analytics operations
  • Service-based data consumption (OData)

ABAP CDS enables using this concept in the ABAP development environment, supporting SAP HANA's "Code-to-Data" principle - bringing code to the database for processing data, thus reducing network traffic and increasing performance.

2. Advantages of ABAP CDS

  • Database-Level Processing: Data processing operations are performed at the database layer, providing significant performance improvements compared to operations at the ABAP layer.
  • Reusability: CDS views are defined centrally and can be reused by multiple applications, reports, and interfaces, reducing code duplication.
  • Rich Data Modeling: Supports powerful features such as calculated fields, associations, parameters, and more.
  • Code Consistency: When data access logic is centralized in CDS views, all applications follow the same business rules.
  • Comprehensive Annotation Support: You can add semantic enrichments for UI rendering, OData services, search support, and more.
  • SAP Fiori Integration: CDS views can be used to define data sources for SAP Fiori applications.
  • Analytical Capabilities: Includes aggregation and drill-down capabilities for analytical querying.
  • Authorization Control: Data access control can be defined directly at the CDS level.

3. Creating CDS Views

3.1 Basic CDS View

Follow these steps to create a CDS view using ABAP Development Tools (ADT):

Step 1: Open your project in Eclipse-based ABAP Development Tools (ADT) or SAP Business Application Studio.

Step 2: Create a new CDS view:

  • Right-click on your project > New > ABAP Repository Object > Core Data Services > Data Definition

Step 3: Name your CDS view (e.g., Z_CUSTOMER_BASIC) and define it as follows:

@AbapCatalog.sqlViewName: 'ZCUSTOMERBASIC'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Customer Basic Data'
define view Z_CUSTOMER_BASIC
  as select from kna1
{
    key kna1.kunnr as CustomerNumber,
    kna1.name1 as CustomerName,
    kna1.land1 as CountryCode,
    kna1.ort01 as City,
    kna1.pstlz as PostalCode,
    kna1.stras as Street,
    kna1.telf1 as Telephone,
    kna1.kunnr as SearchTerm
}
where kna1.loevm = ''  // Select only those not marked as deleted

Annotations:

  • @AbapCatalog.sqlViewName: Specifies the name of the physical SQL view to be created in the database. Must be maximum 16 characters.
  • @AbapCatalog.compiler.compareFilter: Used for better optimization of SQL WHERE clauses.
  • @AccessControl.authorizationCheck: Defines the authorization check level. The value #CHECK indicates that standard SAP authorization checks will be applied.
  • @EndUserText.label: Provides a descriptive label for the view.

3.2 Using Annotations

Annotations are metadata that enrich CDS views for various consumption scenarios. Here's an example with more advanced annotations:

@AbapCatalog.sqlViewName: 'ZCUSTUI'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Customer Data with UI Customization'
@UI: {
  headerInfo: {
    typeName: 'Customer',
    typeNamePlural: 'Customers',
    title: { type: #STANDARD, value: 'CustomerName' }
  }
}
@Search.searchable: true
define view Z_CUSTOMER_UI
  as select from kna1
{
    @UI.facet: [
      { id: 'CustomerDetails',
        purpose: #STANDARD,
        type: #IDENTIFICATION_REFERENCE,
        label: 'Customer Details',
        position: 10 }
    ]
    
    @UI.hidden: true
    key kna1.kunnr as CustomerNumber,
    
    @UI: {
      lineItem: [{ position: 10, importance: #HIGH }],
      identification: [{ position: 10 }],
      selectionField: [{ position: 10 }]
    }
    @Search.defaultSearchElement: true
    kna1.name1 as CustomerName,
    
    @UI: {
      lineItem: [{ position: 20, importance: #MEDIUM }],
      identification: [{ position: 20 }],
      selectionField: [{ position: 20 }]
    }
    @Consumption.valueHelp: '_Country'
    kna1.land1 as CountryCode,
    
    @UI: {
      lineItem: [{ position: 30, importance: #MEDIUM }],
      identification: [{ position: 30 }]
    }
    kna1.ort01 as City,
    
    @UI: {
      identification: [{ position: 40 }]
    }
    kna1.pstlz as PostalCode,
    
    @UI: {
      identification: [{ position: 50 }]
    }
    kna1.stras as Street,
    
    @UI: {
      identification: [{ position: 60 }]
    }
    kna1.telf1 as Telephone
}
where kna1.loevm = ''

Important UI Annotations:

  • @UI.headerInfo: Defines header information in list used in Fiori elements.
  • @UI.facet: Defines UI sections and layout.
  • @UI.lineItem: Specifies which fields should be shown in the list view.
  • @UI.identification: Defines fields shown in the object's detail page.
  • @UI.selectionField: Defines fields to appear in search criteria.
  • @Search.searchable and @Search.defaultSearchElement: Used for search functionality.

3.3 Parameters and Calculated Fields

CDS views can include calculated fields and parameters, allowing you to create dynamic queries:

@AbapCatalog.sqlViewName: 'ZSALESANALYSIS'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales Analysis'
define view Z_SALES_ANALYSIS
  with parameters
    P_DisplayCurrency : waers,
    P_StartDate       : sy-datum,
    P_EndDate         : sy-datum
  as select from vbak
    inner join vbap on vbak.vbeln = vbap.vbeln
    inner join mara on vbap.matnr = mara.matnr
{
    key vbak.vbeln as SalesDocument,
    key vbap.posnr as SalesDocumentItem,
    vbak.audat as DocumentDate,
    vbak.kunnr as CustomerNumber,
    mara.matnr as MaterialNumber,
    mara.mtart as MaterialType,
    vbap.kwmeng as OrderQuantity,
    vbap.meins as SalesUnit,
    
    // Calculated fields
    case when vbap.kwmeng > 0 and vbap.netwr > 0
         then division(vbap.netwr, vbap.kwmeng, 2)
         else 0
    end as UnitPrice,
    
    vbap.netwr as NetAmount,
    
    // Currency conversion (example - real conversion is more complex)
    currency_conversion(
      amount             => vbap.netwr,
      source_currency    => vbak.waerk,
      target_currency    => :P_DisplayCurrency,
      exchange_rate_date => vbak.audat
    ) as ConvertedAmount,
    
    // Using HANA's SQL functions
    days_between(vbak.audat, vbak.erdat) as DaysToProcessing
}
where vbak.audat between :P_StartDate and :P_EndDate
  and vbak.vbtyp = 'C'  // Select only orders

Parameters and Calculated Fields Explanation:

  • with parameters: Defines input parameters for dynamic filters and calculations.
  • Calculated fields: You can use CASE statements, functions, and other SQL expressions.
  • currency_conversion(): SAP's currency conversion function.
  • days_between(): SAP HANA's function to calculate days between dates.

4. CDS Associations

CDS associations allow you to establish connections between CDS views and pre-join data:

@AbapCatalog.sqlViewName: 'ZCUSTORDERS'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Customer with Orders'
define view Z_CUSTOMER_ORDERS
  as select from Z_CUSTOMER_BASIC as Customer
  association [0..*] to vbak as _SalesOrders
    on Customer.CustomerNumber = _SalesOrders.kunnr
  association [0..1] to t005t as _CountryText
    on $projection.CountryCode = _CountryText.land1
    and _CountryText.spras = 'E' // Language code for English
{
    key Customer.CustomerNumber,
    Customer.CustomerName,
    Customer.CountryCode,
    _CountryText.landx as CountryName,
    Customer.City,
    Customer.PostalCode,
    
    // Counting orders (cardinality semantics)
    @Semantics.amount.currencyCode: 'OrdersCurrencyCode'
    _SalesOrders.netwr as TotalOrdersAmount,
    _SalesOrders.waerk as OrdersCurrencyCode,
    
    // Exposing associations
    _SalesOrders,
    _CountryText
}

Explanation of the Above Code:

  • association [0..*]: Defines a one-to-many relationship between customer and orders.
  • association [0..1]: Defines a one-to-one relationship between country code and country description.
  • on $projection.CountryCode: Join conditions are defined using fields from the current projection.
  • _SalesOrders: Alias used to access the association.

Using Associations:

After defining associations, you can create another CDS view that uses these associations:

@AbapCatalog.sqlViewName: 'ZCUSTORDDETAIL'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Customer Order Details'
define view Z_CUSTOMER_ORDER_DETAILS
  as select from Z_CUSTOMER_ORDERS as CustomerOrders
  association [1..*] to vbap as _OrderItems
    on CustomerOrders._SalesOrders.vbeln = _OrderItems.vbeln
{
    key CustomerOrders.CustomerNumber,
    CustomerOrders.CustomerName,
    key CustomerOrders._SalesOrders.vbeln as SalesDocument,
    key _OrderItems.posnr as SalesDocumentItem,
    _OrderItems.matnr as MaterialNumber,
    _OrderItems.arktx as ItemDescription,
    @Semantics.quantity.unitOfMeasure: 'OrderUnit'
    _OrderItems.kwmeng as OrderQuantity,
    _OrderItems.meins as OrderUnit,
    @Semantics.amount.currencyCode: 'DocumentCurrency'
    _OrderItems.netwr as NetAmount,
    _OrderItems.waerk as DocumentCurrency
}

Important points about associations:

  1. Associations are only defined, they don't automatically fetch data
  2. When you want to use associated data, explicitly add it to the projection or expose it
  3. Associations are more flexible and intuitive than using JOINs in CDS views
  4. They work with LEFT OUTER JOIN semantics

5. Creating OData Service with CDS

You can easily publish CDS views as OData services that can be consumed by SAP Gateway:

Step 1: Add OData Annotations to CDS View

@AbapCatalog.sqlViewName: 'ZCUSTODATA'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Customer OData Service'
@OData.publish: true
@ObjectModel.modelCategory: #BUSINESS_OBJECT
@ObjectModel.compositionRoot: true
@ObjectModel.transactionalProcessingEnabled: true
@ObjectModel.writeActivePersistence: 'kna1'
@ObjectModel.createEnabled: true
@ObjectModel.updateEnabled: true
@ObjectModel.deleteEnabled: true
define view Z_CUSTOMER_ODATA
  as select from kna1
{
    @ObjectModel.mandatory: true
    key kna1.kunnr as CustomerNumber,
    
    @ObjectModel.mandatory: true
    kna1.name1 as CustomerName,
    
    kna1.land1 as CountryCode,
    kna1.ort01 as City,
    kna1.pstlz as PostalCode,
    kna1.stras as Street,
    kna1.telf1 as Telephone
}
where kna1.loevm = ''

OData Annotation Explanation:

  • @OData.publish: Publishes the view as an OData service.
  • @ObjectModel.modelCategory: Defines it as a business object model.
  • @ObjectModel.transactionalProcessingEnabled: Enables CRUD (Create, Read, Update, Delete) operations.
  • @ObjectModel.writeActivePersistence: The table where write operations will be performed.
  • @ObjectModel.xxxEnabled: Enables/disables CRUD operations individually.

Step 2: Create Service Definition

In S/4HANA, you need to create an OData service definition and configuration for SAP Gateway:

@EndUserText.label: 'Customer OData Service'
define service Z_CUSTOMER_SRV {
  expose Z_CUSTOMER_ODATA as Customer;
}

Step 3: Activate OData Service

  1. Run transaction /IWFND/MAINT_SERVICE
  2. Click on Add Service
  3. Select the System Alias
  4. Search for Technical Service Name (Z_CUSTOMER_SRV)
  5. Activate the service and save

Step 4: Test the Service

You can test your service with the following URL:

https://<server>:<port>/sap/opu/odata/sap/Z_CUSTOMER_SRV/

The OData service can support:

  • CRUD operations
  • Filtering
  • Sorting
  • Pagination
  • Authorization control

6. CDS Analytical Queries

CDS analytical queries support OLAP capabilities for multidimensional reporting:

@AbapCatalog.sqlViewName: 'ZSALESANAL'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales Analytics'
@Analytics.dataCategory: #CUBE
define view Z_SALES_ANALYTICS
  as select from vbak
    inner join vbap on vbak.vbeln = vbap.vbeln
    inner join kna1 on vbak.kunnr = kna1.kunnr
{
    // Dimensions
    @AnalyticsDetails.query.axis: #FREE
    key vbak.vkorg as SalesOrg,
    
    @AnalyticsDetails.query.axis: #FREE
    key vbak.vtweg as DistChannel,
    
    @AnalyticsDetails.query.axis: #FREE
    key kna1.land1 as CustomerCountry,
    
    @AnalyticsDetails.query.axis: #FREE
    key vbap.matnr as Material,
    
    // Date dimension
    @AnalyticsDetails.query.axis: #FREE
    key vbak.audat as DocDate,
    
    // Measures / Counters
    @DefaultAggregation: #SUM
    @Semantics.amount.currencyCode: 'Currency'
    vbap.netwr as NetAmount,
    
    @DefaultAggregation: #SUM
    @Semantics.quantity.unitOfMeasure: 'BaseUnit'
    vbap.kwmeng as Quantity,
    
    // Currency/unit
    @AnalyticsDetails.query.axis: #FREE
    vbap.waerk as Currency,
    
    @AnalyticsDetails.query.axis: #FREE
    vbap.meins as BaseUnit
}

Important Notes About Analytical Queries:

  • @Analytics.dataCategory: Defines the view as a cube.
  • @DefaultAggregation: Specifies automatic aggregation behavior.
  • @AnalyticsDetails.query.axis: Specifies fields that can be used as dimension/measure.
  • @Semantics: Defines currency and unit of measure relationships.

7. Performance Optimization

Best practices for creating efficient CDS views:

  1. Select Only Necessary Fields: Select what is needed, avoid using "SELECT *".
  2. Use Appropriate Indexes: Ensure fields in WHERE clauses of your CDS views are properly indexed.
  3. Optimize WHERE Clauses: Apply filters as early as possible and allow for index/compare filter optimizations.
  4. Use @AbapCatalog.compiler.compareFilter: true: Enables SAP's filter optimizations.
  5. JOIN Optimization:
    // Instead of this:
    as select from A inner join B inner join C
    
    // Prefer this (allows better optimization):
    as select from A 
      inner join B on ...
      inner join C on ...
  6. Use Associations Instead of Nested Views in CDS: Associations are more flexible and generally better optimized.
  7. Avoid Function Calls in WHERE Clauses: Function calls prevent index usage.
  8. Be Careful with Aggregations for High-Volume Tables: Use analytical annotations for aggregation performance.
  9. Code Pushdown: Push code logic to the database instead of moving data to the application server.
  10. Monitor CDS Query Performance: Use SQL trace and explain plans to analyze performance.

8. Conclusion

ABAP CDS provides a powerful, semantically rich framework for data modeling and access, unlocking the full potential of SAP HANA. When used correctly, it delivers:

  • Higher performance - through the Code-to-Data paradigm
  • Easier maintenance - with central definition of data models within SAP S/4HANA architecture
  • More efficient development - due to reusability and extensibility of data models
  • Modern UI integration - via SAP Fiori and UI annotations
  • Robust analytical capabilities - with built-in analytical functions

When building CDS views, following the learned best practices will help you to have modular and performant CDS views. Study standard CDS views to understand SAP S/4HANA models and extend them in your applications.

Comments

0

You must be logged in to comment.

No comments yet.

Be the first to comment.

Emre Göçmen

Author & Developer

I write about my experiences as a SAP ABAP & Full Stack developer.

Category

SAP

SAP

Subscribe to Newsletter

Subscribe to my newsletter to get notified about new articles.