Skip to content

Prerequisite

Complete Exercise 2 before starting this exercise.

Known issue

HDI deployment can take 2–3 minutes on first run. If it times out, re-run cds build --production and redeploy.

Exercise 3 - Create Database Artifacts Using Core Data Services (CDS) for SAP HANA Cloud

In this exercise you will define a CDS data model, deploy it to SAP HANA Cloud via HDI, and load initial data using the SAP HANA Database Explorer. By the end you will have live database tables backed by HANA and a CAP service exposing them as OData endpoints.

Background

What CDS does for your database

In a standard CAP project you never write raw DDL (CREATE TABLE …). Instead, you describe your data model in CDS (Core Data Services) — a high-level, domain-focused language — and CAP compiles it into the correct HANA artifacts automatically.

When you run cds build --production, CAP translates each CDS entity into an .hdbtable or .hdbview file inside db/src/gen/. The HDI deployer (@sap/hdi-deploy) then pushes those artifacts into an isolated HDI container in your HANA Cloud instance. The container owns the schema, manages versioned deployments, and ensures each project's objects are fully isolated from one another.

The data model in this project

The solution app defines two entities in db/interactions.cds:

cds
context app.interactions {
    entity Headers : cuid, managed {
        items   : Composition of many Items on items.interaction = $self;
        partner : BusinessKey;
        country : Country;
    };

    entity Items : cuid {
        interaction : Association to Headers;
        text        : localized Text;
        date        : DateTime;
        price       : Price;
        currency    : Currency;
    };
}
  • cuid — a CDS aspect that adds a UUID primary key (ID) automatically.
  • managed — a CDS aspect that adds createdAt, createdBy, modifiedAt, modifiedBy audit fields automatically.
  • CompositionHeaders owns Items; deleting a header cascades to its items.
  • AssociationItems holds a back-reference to its parent Headers row.
  • Country / Currency — reused from @sap/cds/common, giving you standardized code-list associations without defining them yourself.

The service layer

srv/interaction_srv.cds exposes projections from the data model as a single OData V4 service named CatalogService. CAP generates the OData metadata document, all CRUD operations, and the $expand / $filter / $orderby query options from the CDS definition alone — no hand-written SQL or route handlers are needed for basic CRUD.

Exercise 3.1 — Define the CDS Model and Deploy to HANA

Create database entities

The SAP Cloud Application Programming model utilizes core data services to define artifacts in the database module. Because this model is meant to be database-agnostic -- i.e., work with any database -- it does not allow you to leverage features that are specific to SAP HANA Cloud. For this reason, you will also create two tables that do not require any advanced data types.

  1. In the db folder, right mouse click and choose New File

    New File

  2. Use the following name:

    Name
    interactions.cds

    Interactions.cds

  3. Use the following content in this new file:

    CAP
    namespace app.interactions;
    
    using {
        Country,
        Currency,
        cuid,
        managed
    } from '@sap/cds/common';
    
    type BusinessKey : String(10);
    type Price       : Decimal(10, 2);
    type Text        : String(1024);
    
    entity Headers : cuid, managed {
        items   : Composition of many Items
                      on items.interaction = $self;
        partner : BusinessKey;
        country : Country;
    };
    
    entity Items : cuid {
        interaction : Association to Headers;
        text        : localized Text;
        date        : DateTime;
        @Semantics.amount.currencyCode: 'currency'
        price       : Price;
        currency    : Currency;
    };

    What is going on?

    You are declaring two entities with relationships between each other. The design-time artifacts declared in this file will be converted to run-time, physical artifacts in the database. In this example, the entities will become tables.

  4. We are using a reusable set of content (lists of countries, currencies, etc) provided by SAP in the above model. We also have to add this dependency to our project. From the command line issue the following command to do so:

    shell
    npm add @sap/cds-common-content --save

Create service interface

  1. In the srv (not src!) folder create another file and name it interaction_srv.cds

    Name
    interaction_srv.cds

    interaction_srv.cds

  2. Use the following content in this new file:

    CAP
    using app.interactions from '../db/interactions';
    using {sap} from '@sap/cds-common-content';
    
    service CatalogService {
    
        @odata.draft.enabled: true
        entity Interactions_Header as projection on interactions.Headers;
    
        entity Interactions_Items  as projection on interactions.Items;
    
        @readonly
        entity Languages           as projection on sap.common.Languages;
    }
  3. Save all.

    What is going on?

    You are declaring services to expose the database entities you declared in the previous step.

  4. From the terminal issue the command: cds build --production

    shell
    cds build --production

    cds build

  5. Look into the console to see the progress. You can scroll up and see what has been built

    cds build log

Explore generated design-time artifacts

  1. If you pay attention to the build log in the console, you will see the CDS artifacts were converted to hdbtable and hdbview artifacts. You will find those artifacts in a new folder under /gen/db/src called gen.

    Results of cds build

  2. You will now deploy those objects into the HANA Database creating tables and views. We will use the SAP HANA Projects view to do this. Please expand this view and you will see the following:

    SAP HANA Projects view

  3. We need to bind our project to a Database Connection and HDI container instance. Press the bind icon to being the process.

    Bind Project

  4. If you receive either of these two following warning dialogs, please just choose Continue (nothing will be deleted because we are create a new HDI Container Instance) and Enable (automatic undeploy is quite helpful during the development process for the reasons described in this dialog)

    Binding Warning #1

    Binding Warning #2

  5. The bind process will start a wizard where you will be prompted for values via the command pallet at the top of the SAP Business Application Studio screen. You might be asked to confirm your Cloud Foundry endpoint and credentials depending upon how long it has been since you last login.

    Confirm Credentials

  6. Your first choice will be for the binding option. Choose Bind to an HDI container.

    Bind to an HDI container

  7. You might be presented with options for existing service instances (if you've completed other tutorials or have performed other HANA development). But for this exercise we want to choose Create a new service instance

    Create a new service instance

  8. To make subsequent steps easier, shorten the generated name to MyHANAApp-dev + a group number or your initials if you are doing this tutorial as part of a group workshop/shared environment. This makes sure that everything remains unique per participant. Remember the value you used here and adjust the name in the subsequent steps. The remaining screenshots will always just show the base name.

    Generated Service Name

  9. It will take a minute or two for the service to be created in HANA. A progress bar will be shown in the message dialog

    Service Creation Progress

  10. Sometimes the binding step fails due to a timing issue. If so simply repeat the binding but this time do not create a new container name but select the existing HDI container that has been created from the previous attempt MyHANAApp-dev

  11. Upon completion, the Database Connections will now show the service bound to the instance the wizard just created.

    Bound Connection

  12. We are now ready to deploy the development content into the database. Before you go ahead, we recommend that you increase the default number of scrollback lines in the integrated terminal, if you're using a Dev Space in SAP Business Application Studio. This is because there are many lines of log output about to be generated and you will want to see them all. So use menu path File -> Preferences -> Settings and search for the "Terminal › Integrated: Scrollback" setting. Set the value to 10000. Now, once you've done that, you're ready to deploy. Press the Deploy button (which looks like a rocket) at the db folder level in the SAP HANA Projects view.

    Deploy

  13. Scroll up to in the console to see what the build process has done.

What is going on?

CDS stands for Core Data Services. This is an infrastructure that allows you to create persistency and services using a declarative language. Notice how you are using the same syntax to define both the persistency and the services.   You can find more information on CDS in the help

You defined a CDS artifact, this is an abstraction, a design-time declaration of the entities to be represented in a database and the services to expose them.   Build database module

The original .cds file was translated into hdbtable, which is the SQLDDL syntax specific to SAP HANA when you saved all of the files.   Build database module

These hdbtable files were then translated into runtime objects such as tables in the HANA database.

Build database module

If you checked the services in your space, you would see the service for your HDI container.

Build database module

You can find a similar example and further context on Core Data and Services in this explanatory video

Check the Database Explorer

You can now check the generated tables and views in the Database Explorer.

  1. In the SAP HANA Projects view, press the Open HDI Container button

    Press Open HDI Container

  2. The Database Explorer will open in a new browser tab and automatically select the database entry for your project's HDI container.

  3. Once open, navigate to the Tables section and click on the Header table.

    Open Table Definition

  4. Note the name of the table matches the generated hdbtable artifacts. You will also see the physical schema managed by the HDI container.

    Unless a name is specified during deployment, HDI containers are automatically created with names relative to the project and user generating them. This allows developers to work on different versions of the same HDI container at the same time. Build database module

Load data into your tables

  1. Download the header file and the items file and the texts file into your local file system.

  2. Right-click again on the header table and choose Import Data.

    Import data

  3. Choose Import Data and press Step 2

    Import data

  4. Choose Local for the Import Data From: option. Browse for the Header file and click Step 3.

    Import data

  5. Keep the default import target and click Step 4.

    Import data

  6. Keep the default table mapping and press Step 5.

    Import data

  7. Keep the default error handling and press Review

    Import data

  8. Choose Import into Database.

    Import data

  9. You will see confirmation that 4 records have imported successfully.

    Import data

  10. Repeat the process with the app.interactions-Items.csv and app.interactions-Items.texts.csv files into the ITEMS and ITEMS_TEXTS tables.

    1Import data

Check data loaded into the tables

  1. You can now check the data loaded into the tables. Right-click on the Items table and click Generate Select Statement.

    Generate select statement

  2. Add the following WHERE clause to the SELECT statement and execute it to complete the validation below.

    SQL
    where "TEXT"  like '%happy%';

What the tutorial covers: You will create the db/interactions.cds data model, add the service projection in srv/interaction_srv.cds, run cds build --production to generate the HDI artifacts, and then deploy them into your HANA Cloud instance using the MTA build and deploy tools in BAS.

Where the generated files go: After cds build --production, look inside db/src/gen/ — you will find .hdbtable files for each entity and .hdbview files for any CDS views. These are the HANA-native artifacts that HDI manages. You do not edit these files directly; they are regenerated every time you build.

Exercise 3.2 — Load Data Using the SAP HANA Database Explorer

Once the tables exist in HANA, use the Database Explorer to import sample data.

👉 Follow the data-import steps in the tutorial above. Use the Import Data wizard in the Database Explorer to upload the provided CSV files into APP_INTERACTIONS_HEADERS and APP_INTERACTIONS_ITEMS.

Why the Database Explorer? The Database Explorer connects directly to your HANA Cloud instance and lets you browse schemas, run SQL, inspect HDI containers, and import data — all without leaving the browser. It is the primary tool for ad-hoc database work during development.

Naming convention: CAP maps the CDS context app.interactions and entity Headers to the HANA table name APP_INTERACTIONS_HEADERS. The dot-separator becomes an underscore and everything is uppercased. Keep this mapping in mind when writing raw SQL queries against your HDI schema.

Summary

At the end of this exercise you have:

  • A CDS data model (db/interactions.cds) with two related entities using cuid, managed, Composition, and Association
  • A CAP service (srv/interaction_srv.cds) exposing the entities as an OData V4 CatalogService
  • HANA tables deployed into your HDI container via the MTA build and deploy pipeline
  • Sample data loaded into those tables via the SAP HANA Database Explorer

Questions for Discussion

  1. We loaded data using the Database Explorer import wizard. Are there alternatives for getting initial data into CAP tables?

    Answer

    Yes — the most common CAP-native approach is to place CSV files in the db/data/ folder. Name each file after the entity it targets using the fully qualified namespace, for example:

    text
    db/data/app.interactions-Headers.csv
    db/data/app.interactions-Items.csv

    CAP detects these files automatically and loads them during cds deploy (local SQLite) or as part of an HDI deployment. For HANA targets the data is seeded using .hdbtabledata artifacts that CAP generates from the CSV files.

    SAP Build Code also has an AI-assisted CSV generator that can create realistic sample data from your CDS model in seconds.

    When to use HANA Table Import (Database Explorer) instead of CSV files:

    • Large data sets — HDI table import streams data directly; CSV files via CAP load everything in memory first.
    • External sources — you can import from spreadsheets, other database tables, or custom formats.
    • Incremental loads — import only new or changed rows without a full redeployment.
    • Data transformations — apply column mappings or default values during import.

    The CSV-in-project approach wins for reproducibility: the data travels with the code and is automatically available in every developer environment and CI pipeline.

  2. Where does Country come from in interactions.cds? Hint

    Answer

    At the top of db/interactions.cds you will find:

    cds
    using {
        Country,
        Currency,
        cuid,
        managed
    } from '@sap/cds/common';

    @sap/cds/common is a built-in CDS library (part of the @sap/cds package) that ships a set of pre-built aspects, types, and code-list entities used across nearly every SAP business application:

    NameWhat it provides
    cuidA key ID : UUID field, auto-generated by CAP
    managedcreatedAt, createdBy, modifiedAt, modifiedBy audit fields
    CountryAn association to sap.common.Countries (ISO 3166 alpha-2 codes)
    CurrencyAn association to sap.common.Currencies (ISO 4217 codes)
    LanguageAn association to sap.common.Languages (BCP 47 tags)

    The companion package @sap/cds-common-content seeds the Countries, Currencies, and Languages code-list tables with their standard values at deployment time.

    By reusing these common definitions you get consistent field names and structures across all CAP projects, and tools like Fiori Elements can automatically render country/currency pickers and locale-aware labels.

  3. What is the difference between Composition and Association?

    Answer

    Both model relationships between entities, but they differ in ownership and lifecycle:

    Composition — the child cannot exist without the parent.

    In db/interactions.cds, Headers owns Items:

    cds
    entity Headers : cuid, managed {
        items : Composition of many Items on items.interaction = $self;
        ...
    };
    • Deleting a Headers row automatically deletes all its Items (cascading delete).
    • CAP's deep-insert and deep-update APIs let you create a header and all its items in a single OData request.
    • OData draft mode (enabled on Interactions_Header in interaction_srv.cds) requires a Composition root — it cannot be applied to a standalone Association.

    Association — the related entity can exist independently.

    Items holds a back-reference to its parent via an Association:

    cds
    entity Items : cuid {
        interaction : Association to Headers;
        ...
    };
    • Deleting an Items row does not affect Headers.
    • Associations map to foreign-key columns in HANA (here: INTERACTION_ID).
    • Use Associations when modelling relationships between independently-managed entities, for example linking an order to a product catalogue entry.

    Rule of thumb: if the child's existence is meaningless without the parent (like order line items), use Composition. If both sides can live and be managed independently, use Association.

  4. In interaction_srv.cds, how do you know that CAP is creating an OData service?

    Answer

    The service keyword in CDS always produces an OData service in CAP — it is the default protocol. No extra annotation is needed to opt in to OData; you would need an explicit annotation to opt out.

    Looking at the solution's srv/interaction_srv.cds:

    cds
    service CatalogService {
    
        @requires           : 'authenticated-user'
        @cds.redirection.target
        @odata.draft.enabled: true
        entity Interactions_Header as projection on interactions.Headers;
    
        @requires: 'Admin'
        entity Interactions_Items  as projection on interactions.Items;
    
        @readonly
        entity Languages           as projection on sap.common.Languages;
    
        function sleep() returns Boolean;
    }

    Several signals confirm this is an OData V4 service:

    • service CatalogService { … } — CAP compiles this into an OData service descriptor and registers it at /catalog/ (by convention, lowercase service name without "Service").
    • @odata.draft.enabled: true — activates the OData Draft protocol (specific to OData V4) on Interactions_Header.
    • function sleep() returns Boolean — CDS function maps to an OData Function Import (a GET-based action in OData terminology).
    • @readonly — restricts the OData capabilities to GET only (no POST/PATCH/DELETE).

    When you run the CAP server, you can confirm the service is live by navigating to $metadata (e.g. http://localhost:4004/catalog/$metadata) — this is the OData service document that describes every entity set, property, and function.

  5. What is a CDS aspect, and why are cuid and managed used here instead of defining the fields manually?

    Answer

    A CDS aspect is a named, reusable fragment of a CDS definition — similar to a mixin or trait in other languages. You apply it to an entity with : syntax:

    cds
    entity Headers : cuid, managed { … }

    This is exactly equivalent to writing:

    cds
    entity Headers {
        key ID        : UUID;
        createdAt     : Timestamp @cds.on.insert : $now;
        createdBy     : String(255) @cds.on.insert : $user;
        modifiedAt    : Timestamp @cds.on.insert : $now  @cds.on.update : $now;
        modifiedBy    : String(255) @cds.on.insert : $user @cds.on.update : $user;
    
    }

    The @cds.on.insert and @cds.on.update annotations tell the CAP runtime to populate those fields automatically — you never set createdAt or modifiedBy manually. CAP handles it for every INSERT and UPDATE operation, regardless of whether the request comes via OData, a CAP handler, or the cds.run() API.

    Using cuid and managed means:

    • Every entity in the project gets a consistent, UUID-based primary key — no accidental integer keys or composite keys.
    • Audit fields are guaranteed to be present and correctly populated without any custom handler code.
    • Fiori Elements can automatically detect and display the audit fields in the object page.
  6. After running cds build --production, look inside db/src/gen/. What files were generated, and how do they correspond to the CDS entities you defined?

    Answer

    Inside db/src/gen/ you will find files like:

    text
    APP_INTERACTIONS_HEADERS.hdbtable
    APP_INTERACTIONS_ITEMS.hdbtable

    Each .hdbtable file is an HDI table artifact containing the SQL CREATE TABLE DDL that HANA will execute when the HDI deployer runs. CAP derives the filename from the CDS entity's fully-qualified name: the context prefix app.interactions becomes APP_INTERACTIONS_, and the entity name Headers becomes HEADERS, all uppercased.

    If your CDS model includes views (e.g. projections with computed fields), CAP generates .hdbview files for those instead. These generated files are the bridge between your high-level CDS definitions and the HANA-native artifacts that @sap/hdi-deploy pushes into the database. Never edit them directly — regenerate them by re-running cds build --production.

  7. What would happen if you ran cds build without the --production flag? Why does HANA deployment require it?

    Answer

    Without --production, cds build generates artifacts for the default local database — SQLite. It produces a gen/srv/ folder containing the CAP Node.js runtime bundle but does not generate the .hdbtable/.hdbview files in db/src/gen/ that @sap/hdi-deploy needs.

    The --production flag activates the HANA build profile, which tells CAP to generate HDI-compatible artifacts instead of SQLite-compatible ones. Forgetting the flag is one of the most common deployment mistakes: the mbt build command succeeds, the .mtar archive is created, cf deploy runs — but the db-deployer finds nothing to push into HANA and the deployment either fails or leaves the database schema unchanged.

Further Study

Next

Continue to 👉 Exercise 4 - Create a User Interface with CAP (SAP HANA Cloud)