Migrating to CDS View Entities: Moving DDIC-Based CDS Views

The CDS views we wrote with define view for years have been succeeded by define view entity. The old views keep working, but they get no new features and do not exist in ABAP Cloud at all. This article covers the differences between the two generations, what breaks during migration, and a safe migration plan.
ABAP CDS
CDS View Entity
ABAP Cloud
S/4HANA

Mustafa Önder · 31 October 2026 · 13 min read

When CDS first arrived, every view produced two objects: the CDS entity itself and a DDIC SQL view named with @AbapCatalog.sqlViewName. CDS view entities, introduced with ABAP 7.55 (S/4HANA 2020), removed that second object. There is now one name and one object.

SAP has stated that it will not remove the old views (now called DDIC-based views in the documentation), but new features are added only to view entities; the ABAP keyword documentation also lists DEFINE VIEW among the obsolete statements. This article covers what to watch for when you migrate existing views. It is based on SAP's ABAP documentation and SAP's published articles on the migration; details can vary by release, so compare with your own system's documentation.

Two Generations of CDS: What Changed?

Topic
DDIC-based view (define view)
View entity (define view entity)

Generated objects

CDS entity + DDIC SQL view

CDS entity only

Name

DDL source, CDS entity and SQL view can have different names

DDL source and entity name are the same

Client

Handled with @ClientHandling annotations

Automatic; these annotations are not supported

Parameter access

:p_param or $parameters.p_param

$parameters.p_param only

SELECT *

Supported

Not supported; list the fields explicitly

Extension

EXTEND VIEW (with a DDIC append view)

EXTEND VIEW ENTITY (no append view)

ABAP Cloud

Not available

The only option

New features

None

Ongoing

Activation differs too: because no SQL view is generated, there are fewer DDIC dependencies and activation is faster. View entity syntax is also stricter; some forms the old view tolerated (such as an alias without AS) are errors here.

Why Migrate, and When to Wait?

  • New development: No debate here; SAP also recommends writing new views only as view entities. In the ABAP Cloud language version there is no other option anyway.
  • An old view you are about to change: If you are touching a view anyway, adding the migration to the same task is usually the cheapest moment, since it will be tested regardless.
  • A view nobody touches and that works fine: No rush. Migration is voluntary and the old views remain supported. First work out the dependencies described below.

In some cases migration is not (yet) possible or is expensive:

  • The data source is a DDIC database view or a DDIC external view (view entities do not accept these as a source, join or association target).
  • The view uses DECIMAL_SHIFT (CURR_TO_DECFLOAT_AMOUNT or GET_NUMERIC_VALUE are suggested instead, but the result type changes).
  • The SQL view is read from outside the ABAP layer: database-level reporting tools, native SQL, or another application built on the SQL view.

Before and After: Converting a View

Below is a simple header view similar to the expense form in the RAP project example. First, the DDIC-based version:

@AbapCatalog.sqlViewName: 'ZVEXPREPORT'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Expense report'
define view Z_I_ExpenseReport
  as select from zexp_report
  association [0..*] to Z_I_ExpenseItem as _Item
    on $projection.ReportId = _Item.ReportId
{
  key report_id    as ReportId,
      company_code as CompanyCode,
      employee     as Employee,
      report_date  as ReportDate,
      @Semantics.amount.currencyCode: 'Currency'
      total_amount as TotalAmount,
      @Semantics.currencyCode: true
      currency     as Currency,
      _Item
}

The same view as a view entity:

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Expense report'
define view entity Z_I_ExpenseReport
  as select from zexp_report
  association [0..*] to Z_I_ExpenseItem as _Item
    on $projection.ReportId = _Item.ReportId
{
  key report_id    as ReportId,
      company_code as CompanyCode,
      employee     as Employee,
      report_date  as ReportDate,
      @Semantics.amount.currencyCode: 'Currency'
      total_amount as TotalAmount,
      currency     as Currency,
      _Item
}

What changed: the sqlViewName, compareFilter and preserveKey annotations are gone (there is no SQL view for them to describe; compareFilter is always on in view entities and cannot be changed), define view became define view entity, and @Semantics.currencyCode on the currency field was removed. The amount field is still linked to its currency with @Semantics.amount.currencyCode; in view entities this link is mandatory for CURR fields.

Rules That Change in Migration

  • Parameters: The colon syntax is gone; only $parameters is used.
  • Aliases and prefixes: AS is mandatory for aliases; in views with joins or associations every field is written with its source prefix.
  • Annotation position: @< annotations written after an element are not accepted; annotations precede the element.
  • Units and currencies: @Semantics.currencyCode and @Semantics.unitOfMeasure are not supported; the link is set on the amount/quantity field with @Semantics.amount.currencyCode and @Semantics.quantity.unitOfMeasure.
  • Client field: Since client handling is implicit, the @ClientHandling annotations and the client field in the select list go away.
  • Buffering: DDIC buffering annotations are not supported in view entities.
  • UNION: Key elements must match across branches; element annotations are written only in the first branch. Element types and lengths can also be determined by the first branch, so check later branches for truncation.
  • Aggregation: AVG needs an explicit result type (AVG( ... AS ... )).
// DDIC-based view
where report_date >= :p_from_date

// CDS view entity
where report_date >= $parameters.p_from_date

Note: This list is not complete. SAP's migration report lists in detail which rule applies to each view; also check the list of differences in your release's documentation.

Everything That Depends on the SQL View

The real risk of migration is not in the CDS source but in everything that uses the SQL view that gets deleted. The DDIC SQL view is deleted during migration, and every scenario relying on it stops working. The most common case is ABAP code reading the view by its SQL view name:

" Before: by the DDIC SQL view name (no longer compiles after migration)
SELECT FROM zvexpreport
  FIELDS reportid, companycode, totalamount, currency
  WHERE companycode = @lv_company_code
  INTO TABLE @DATA(lt_reports).

" After: by the CDS entity name (DCL is applied as well)
SELECT FROM z_i_expensereport
  FIELDS ReportId, CompanyCode, TotalAmount, Currency
  WHERE CompanyCode = @lv_company_code
  INTO TABLE @DATA(lt_reports).

There is an easily missed behavioral difference here: CDS access control (DCL) is applied only when the CDS entity is read. Old code reading by the SQL view name bypassed the authorization filter; once it switches to the entity name, for views with @AccessControl.authorizationCheck: #CHECK the user sees only the rows they are authorized for. That is usually correct, but it can come back as a "the report is missing data" complaint. See the CDS authorization and DCL article for details.

Other dependencies to list before migrating:

  • Extensions: Extensions written with EXTEND VIEW and their DDIC append views. New extensions are written with EXTEND VIEW ENTITY; verify the state of existing extensions after migration in a test system.
  • Search helps: A search help assigned directly to the SQL view loses that assignment during migration.
  • Use via DDIC: Other DDIC objects using the SQL view as a data source, access through tools like SE16, BW or data extraction scenarios.
  • Database-level access: Native SQL, AMDP or external tools reading the SQL view directly.

Migration Tools

Tool
What it does
Release

RUTDDLS_MIGRATION_CANDIDATES

Analysis: lists which views can be migrated and what blocks them

ABAP 7.55 and later

RUTDDLSV2MIGRATION

Migration: applies the rules and creates an inactive new version of the view; run it in simulation mode first

ABAP 7.56 (ABAP Platform 2021) and later

Manual migration in ADT

Edit the source in ADT and activate it

ABAP 7.56 and later

The migration report does not activate the view; activation is the developer's final step, and the SQL view is deleted at that moment. Newer releases may also offer a wizard in ADT for the same job. One prerequisite is that the DDL source name and the CDS entity name are the same; if they differ, migration is not possible.

No way back: A migration done with the tool cannot be undone. Reverse migration requires a support ticket with SAP on component BC-DWB-DIC. So migrate first in a development system, with views whose dependencies you have already worked out.

Step-by-Step Migration Plan

  1. Inventory: List the DDIC-based views in your Z/Y namespace and the output of RUTDDLS_MIGRATION_CANDIDATES.
  2. Dependencies: For each view, find where the SQL view name is used (where-used list, code search), plus extensions and search helps.
  3. Order: Start with lower-layer views that have no blockers and no external consumers; work upwards.
  4. Code fix: Switch ABAP code that uses the SQL view name to the entity name before the migration. This step also works with the old view, so it can be transported separately and the DCL effect tested on its own.
  5. Simulate and migrate: Run RUTDDLSV2MIGRATION in simulation, read the warnings, then migrate and activate.
  6. Test: Compare row counts and totals of the same query before and after; open the Fiori apps and OData services.
  7. Transport: Put changed code and views in the same transport request; otherwise code in the target system may look for an SQL view that no longer exists.

Common Mistakes

Migrating the view first and searching the code later

Code reading the SQL view fails with a syntax error after migration. Find the usages first and fix the code first.

Not testing the DCL effect

Old code switched to the entity name now goes through the authorization filter. Also test with a user who has restricted authorizations.

Putting code and view in separate transports

If the view reaches production first, the SQL view is deleted and the old code breaks. Ship both in the same transport or in the right order.

Activating without reading the warnings

Removing compareFilter and client annotations can change the meaning of some views. The warnings in the simulation output show exactly these.

Conclusion

Moving to view entities is more a dependency task than a syntax task. Changes in the CDS source are mostly mechanical, and the tools do most of them. The real work is finding the code, extensions and external consumers that use the SQL view in advance. Write new views as view entities from today; migrate old ones when you touch them, after working out their dependencies.

For the service side with CDS, see the OData V4 and CDS article; for ABAP Cloud rules, the ABAP Cloud and Clean Core article; for the development scope I offer, the SAP development services page.

Get support taking inventory of your CDS views, finding their dependencies and planning a safe migration to view entities.