sapui5tutors SAPUI5 • Fiori • SAP BTP Step-by-step tutorials Real project examples Interview Q&A
Practical SAPUI5 • Fiori • SAP BTP tutorials and interview prep
Showing posts with label ABAP Cloud. Show all posts
sapui5tutors

CDS Table Functions in ABAP: SQLScript as a CDS Entity

20:41:00

CDS views handle most data modeling beautifully — until they don't. You need a recursive hierarchy explosion, a complex procedural calculation, or logic that simply can't be expressed declaratively. Rewriting everything as a raw AMDP call works, but you lose the CDS superpowers: a typed entity, parameters, reusability in other views. CDS table functions give you both: a CDS entity whose rows are produced by an AMDP method.


What a table function is

A CDS table function looks like a CDS entity — it has a name, parameters, and a field list — but instead of a SELECT, its implementation is an AMDP method written in SQLScript. Consumers query it like any table or view:

SELECT FROM ztf_bom_explosion( p_matnr = '100-100' )
  FIELDS matnr, component, quantity, level
  INTO TABLE @DATA(lt_bom).

The caller sees a table. Underneath, an AMDP procedure ran the recursive logic. That separation — declarative interface, procedural implementation — is the whole idea.

Key takeaway: A CDS table function is a CDS entity implemented by an AMDP method. You get SQLScript's full power behind a clean, reusable, typed CDS interface.

Defining one: the CDS side

The DDL is compact. You declare parameters and the result structure, and point at the implementing class:

define table function ZTF_BOM_EXPLOSION
  with parameters p_matnr : matnr
  returns {
    matnr     : matnr;
    component : matnr;
    quantity  : menge_d;
    level     : int4;
  }
  implemented by method
    zcl_bom_functions=>explode_bom;

Everything a consumer needs — parameter names and types, the exact shape of the result — is declared here. The CDS tooling validates consumers against this contract, so a typo in a field name fails at design time, not at 2 AM in production.


The AMDP side

The implementing method follows the standard AMDP pattern — IF_AMDP_MARKER_HDB, BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT — with parameters matching the CDS declaration. For a BOM explosion, the SQLScript body uses a recursive CTE or a HANA hierarchy function to walk the structure:

METHOD explode_bom BY DATABASE PROCEDURE
  FOR HDB LANGUAGE SQLSCRIPT
  OPTIONS READ-ONLY.
  lt_result = SELECT ... FROM HIERARCHY ( ... );
ENDMETHOD.

(Body simplified — the point is the pattern, not the specific hierarchy syntax.) The method's importing/exporting parameters must line up exactly with the CDS parameters and return fields; the activation will tell you when they don't.


Consuming table functions in CDS views

Table functions really earn their keep when other CDS views consume them. A view can join the table function like any table:

define view entity ZV_BOM_COSTING as select from ztf_bom_explosion( p_matnr = '100-100' ) as bom
  inner join zmaterial_price as price
    on price.matnr = bom.component
{
  bom.component,
  bom.quantity,
  bom.quantity * price.unit_price as extended_cost
}

Now the procedural BOM walk is a reusable building block inside the declarative CDS world — joinable, filterable, and consumable by OData services and Fiori apps without anyone knowing SQLScript was involved.


Parameters, client handling, and testing

Two practical details catch people out. First, parameters are mandatory — every call must supply every declared parameter; there are no optional parameters with defaults like in some other frameworks. Design the parameter list accordingly: keep it small and meaningful.

Second, client handling is your responsibility. Unlike a CDS view entity, a table function's AMDP body doesn't get automatic client filtering — you must include the client field in your logic, typically by reading the session context (SESSION_CONTEXT('CLIENT')) inside the SQLScript and filtering on it explicitly. Forget this and your function cheerfully returns other clients' data. It's the single most common table-function bug in code reviews, and it's worth a dedicated check.

For testing, start outside ABAP: run SELECT against the table function directly in the HANA SQL console with literal parameter values. If the logic is wrong there, no ABAP wrapper will fix it. Once the SQL is right, test the CDS consumption in a small ABAP report before wiring it into views and services.


When to use them (and when not to)

Use table functions for logic that genuinely needs SQLScript: hierarchies, recursion, complex procedural calculations, or HANA-specific functions with no CDS equivalent.

Don't use them as a shortcut around learning CDS. If a plain view with associations and calculated fields can express it, the plain view wins — better tooling, better extensibility, portable across databases.

And remember the clean-core angle: in ABAP Cloud, table functions are a sanctioned escape hatch for complex data logic. They keep the complexity inside the data model, behind a stable contract, instead of leaking procedural code into every consumer. That's exactly where you want it.

Read more →
sapui5tutors

ABAP Managed Database Procedures (AMDP): A Practical Guide

20:39:00

Every ABAP developer hits the same wall: the logic you need is easy in SQL, awkward in ABAP. Recursive queries, complex window functions, set-based operations over millions of rows — you can do them in ABAP, but you end up pulling data to the app server and looping, which is the slowest possible place to do it. ABAP Managed Database Procedures (AMDP) let you write database procedures — in SQLScript — managed as ABAP repository objects.

The key word is managed. You're not creating stored procedures in the database by hand. You write an AMDP method in an ABAP class, and the ABAP system transports it, activates it, and manages its lifecycle like any other ABAP object.


When AMDP makes sense

Reach for AMDP when the database can do the job fundamentally better than the app server:

Set-based heavy lifting. Aggregations, ranking, running totals over large datasets. SQLScript's window functions and grouping do in one pass what ABAP loops do in a million iterations.

Things SQL does natively. Recursive CTEs for hierarchies, complex joins the CDS view editor can't express, graph or text-processing functions in HANA.

Performance-critical paths. When a CDS view gets you 90% of the way but the last 10% kills performance, an AMDP procedure can take over the hot part.

Don't reach for AMDP for plain CRUD or simple selects — CDS views and plain ABAP SQL cover those with better tooling, testability, and portability.

Key takeaway: AMDP = SQLScript procedures managed as ABAP objects. Use them for database-side heavy lifting (aggregations, hierarchies, window functions) — not for everyday selects, where CDS views are the better tool.

The anatomy of an AMDP method

An AMDP is a method of a global class, tagged with interface IF_AMDP_MARKER_HDB and implemented BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT. A minimal example computing running totals:

CLASS zcl_sales_analytics DEFINITION PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_amdp_marker_hdb.
    TYPES: BEGIN OF ty_result,
             bukrs  TYPE bukrs,
             period TYPE char6,
             amount TYPE dmbtr,
             running TYPE dmbtr,
          END OF ty_result,
          tt_result TYPE STANDARD TABLE OF ty_result.
    METHODS get_running_totals
      IMPORTING VALUE(iv_bukrs) TYPE bukrs
      EXPORTING VALUE(et_result) TYPE tt_result.
ENDCLASS.

CLASS zcl_sales_analytics IMPLEMENTATION.
  METHOD get_running_totals BY DATABASE PROCEDURE
    FOR HDB LANGUAGE SQLSCRIPT
    OPTIONS READ-ONLY.
    et_result = SELECT bukrs, period, amount,
      SUM(amount) OVER (PARTITION BY bukrs
        ORDER BY period) AS running
      FROM zsales_data
      WHERE bukrs = :iv_bukrs;
  ENDMETHOD.
ENDCLASS.

Note the details: parameters use VALUE(), host variables are prefixed with :, and the result is assigned to the exporting table parameter. OPTIONS READ-ONLY declares the procedure won't modify data — include it whenever true, because the system can optimize accordingly.


Calling AMDP from ABAP

From the caller's side, an AMDP method looks like any other method:

DATA(lo_analytics) = NEW zcl_sales_analytics( ).
lo_analytics->get_running_totals(
  EXPORTING iv_bukrs  = '1000'
  IMPORTING et_result = DATA(lt_result) ).

The caller doesn't know (or care) that the logic executed as SQLScript inside HANA. That encapsulation is the point: the database-specific code lives behind a clean ABAP interface, so the rest of your application stays portable and testable.


AMDP and CDS: better together

AMDPs shine brightest as the implementation behind CDS table functions — you define the CDS entity with its parameters and fields, and the AMDP method supplies the rows. The CDS layer gives you a typed, documented, reusable interface; the AMDP gives you full SQLScript power underneath. It's the standard pattern for logic that's too complex for a plain CDS view.

One practical rule: prefer a CDS view first, drop to AMDP-backed table functions only when the view can't express what you need. Views get better tooling (annotations, associations, extensibility); AMDPs get raw power. Choose per case, and document why the AMDP was necessary — future you will want to know.


Pitfalls to avoid

Portability. SQLScript is HANA-specific. If your code must run on other databases, AMDP is off the table — that's exactly what the FOR HDB clause declares.

Debugging. You can't step through SQLScript in the ABAP debugger the way you step through ABAP. Test the SQL logic independently (SQL console first, AMDP wrapper second), and keep procedures small enough to reason about.

Security. AMDPs run with the database user's authorizations. OPTIONS READ-ONLY is your friend; think twice before writing procedures that modify data, and never build dynamic SQL from untrusted input.

Used with discipline — database work in the database, behind a clean ABAP interface — AMDP turns "impossible in ABAP" logic into a method call.

Read more →