CDS Access Controls and DCL Explained
DCL (Data Control Language) is the syntax used to write CDS access control sources, which filter rows returned by a CDS view or view entity based on the current user's authorization. A CDS entity is linked to a DCL source through the authorizationCheck annotation; if that link or the DCL source itself is broken, the entity silently returns zero rows rather than raising an error.
This page covers how CDS access controls and DCL sources restrict row-level data returned through CDS view entities, how they connect to classic PFCG authorization objects, and where they sit relative to RAP business objects and OData services. It focuses on the diagnostic patterns that cause silent data loss or authorization leaks in real projects.
Published 16 Sept 2026· 1,413 words
What it is
DCL is the language behind CDS access controls: a separate repository object (a role, in the DCL sense) that defines a where-clause style filter applied automatically to a CDS entity's result set. The CDS entity itself only carries an annotation, typically something like authorizationCheck set to CHECK, NOT_REQUIRED or PRIVILEGED, pointing at the DCL source by name. The single structural fact that explains most confusion: the annotation and the DCL source are two separate objects joined only by a name reference, activated independently. If the DCL source is missing, inactive, or the reference is misspelled, the framework does not throw an authorization error — it treats the entity as fully restricted and returns an empty result. This looks exactly like a broken join, a missing association, or bad test data, and gets debugged as such for hours before anyone checks whether the DCL source even exists or is active.
When to use it
Use CDS access controls whenever the same business data must be filtered consistently across every consumption path: a Fiori app, a RAP business object, an ad hoc CDS-based query, and a custom report all reading the same view entity. This is the right tool when the restriction is a genuine authorization concern tied to an existing or new PFCG authorization object, such as restricting by sales organization, plant, or company code. It is the wrong tool for purely technical filtering that has nothing to do with user authorization, such as excluding test records or limiting a dataset for performance — use a normal selection parameter or filter for that. It is also the wrong tool for field-level masking or for write authorization; DCL restricts which rows come back on read, not which fields are visible or which operations a user may execute.
How it fits the stack
In the read path, the CDS view or view entity sits above the DCL source and carries the annotation that activates it. The DCL source itself sits above the classic PFCG authorization object and role infrastructure, since its where-clause typically resolves fields against an authorization object's activity and organizational fields rather than reinventing authorization logic. Above the CDS entity sit all its consumers: RAP business objects, OData services and their Fiori elements apps, analytical queries, and plain ABAP SELECT statements against the entity with authorization checks enabled. DCL supersedes the pattern of embedding authority-check statements inside every individual report or function module that touches the same table; instead the check is centralized once at the data-access layer and inherited by every consumer that reads through that entity.
A worked example
A sales order header view entity is exposed through a RAP business object and consumed by a Fiori elements list report. The requirement is that users only see orders belonging to sales organizations they are authorized for, using an existing authorization object that already controls sales organization access elsewhere in the system. The view entity's authorizationCheck annotation is set to CHECK and pointed at a new DCL source. The DCL source's where-clause maps the entity's sales organization field against the authorization object's organizational field and activity, using the aspect pfcg_auth construct rather than hardcoding values. After activation, a user with only one sales organization in their role sees a correctly filtered list. A second issue then surfaces: the business partner data reachable through an association on the same entity was left with authorizationCheck set to NOT_REQUIRED on its own view entity, so partner details for orders the user should not see are still visible through drilldown. The fix is aligning the check level on every entity reachable through the composition, not just the top-level one.
How to choose
- DCL versus classic authority-check calls in ABAP coding: DCL only protects consumers that read through the annotated CDS entity itself. Native SQL, direct table reads, or older reports bypassing the entity bypass the filter entirely. Map every read path before assuming the control is complete.
- CHECK versus NOT_REQUIRED versus PRIVILEGED: PRIVILEGED should be reserved for internal framework consumption such as certain determinations or table functions that are never exposed directly to an end user; setting it on a user-facing entity for convenience removes the control silently.
- One DCL source per entity versus reusing one role across several entities: reuse cuts maintenance but couples unrelated business objects to the semantics of one authorization object, so a later change to that object's fields forces an impact analysis across every entity sharing the role.
- Aspect pfcg_auth versus session-based filters such as restricting by the current user: pfcg_auth integrates with existing PFCG-maintained authorization objects that functional teams already know from SU24; a session-based ownership filter is simpler for straightforward created-by checks but does not plug into the existing role concept and needs its own documentation.
- Performance impact: the DCL filter becomes part of the generated SQL where-clause on every read. A complex aspect call against a high-cardinality field on a large table can measurably slow queries; check whether the filter field is already indexed or whether a simpler proxy field would do the same job.
Common pitfalls
- Entity works under a broad test authorization in development, then returns zero rows for real business users because the DCL source is inactive or the annotation references the wrong name. No error is raised, so it presents as a data bug rather than an authorization one.
- Inconsistent check levels across an entity graph: the header entity is properly restricted while an associated item or partner entity is left at NOT_REQUIRED, giving full read access to child data the restriction was meant to cover.
- Underlying authorization object fields change in SU21 and the DCL source is not reactivated to match, producing either a runtime failure or, worse, a filter that silently stops matching anything correctly.
- Testing is only ever done with a broad developer authorization, so the restriction is never actually exercised until a production incident exposes it.
- Assuming DCL covers write operations. As commonly used with CDS view entities and RAP, it is a read filter only; create, update and delete authorization still has to be enforced separately in the RAP behavior implementation or via classic authority-check.
- Layering additional authority-check calls on top of an already-active DCL filter without checking for interaction, producing results that are hard to explain because two independent filters are both silently trimming the same result set.
ECC, S/4HANA and clean core
On S/4HANA, CDS access controls are the standard mechanism for read authorization on custom CDS entities and RAP business objects, and they fit cleanly within clean core principles because both the DCL source and the authorization object it maps to live in customer namespace using released interfaces. Embedding ad hoc authority-check logic inside custom reports is discouraged wherever a released CDS entity with a proper access control already exists for the same data; extensions built for longevity should expose data only through entities that carry an explicit authorization check rather than leaving NOT_REQUIRED as a default. No specific release dependency is assumed here beyond this general direction.
Whose problem this is
The developer writes the DCL source and sets the annotation on the CDS entity. The architect decides the overall strategy: shared versus dedicated roles, and consistent check levels across composed and associated entities. The functional or security team owns the underlying authorization object and its field values in PFCG. Handover should include the DCL source, the mapped authorization object, and a test matrix of role versus expected visible rows.
Related SAP objects
Reviewed pages this object connects to in the ERPClimb knowledge graph.
Source: ERPClimb — https://erpclimb.com/sap-technical-topics/cds-access-controls-and-dclERPClimb is an independent platform and is not affiliated with SAP SE. Reference pages are written and reviewed by SAP consultants for learning and troubleshooting.