| Feature | SQL View | CDS View |
|---|---|---|
| Basic select | CREATE VIEW v AS SELECT * FROM table | define view v as select from table |
| Alias | SELECT a.col FROM tab a | select from tab as a |
| Join | INNER/LEFT/RIGHT JOIN | association [1:1] / [1:n] |
| Filtering | WHERE clause | where condition |
| Grouping | GROUP BY | group by fields |
| Sorting | ORDER BY | order by field asc/desc |
| Annotation | N/A | @annotation: value |
| Parameter | Variable in trigger | @Parameter.parameter |
| Calculation | CASE expression | cast(...as type), calculation |
| Access control | Views only | @AccessControl.authorizationCheck |
HANA CDS Views Essential Cheat Sheet
Comprehensive reference guide for HANA Core Data Services (CDS) including view definitions, associations, annotations, calculations, and professional development best practices.
Quick Reference
Most commonly used CDS features at a glance
About HANA CDS Views
CDS (Core Data Services) provides a powerful abstraction layer over HANA database with semantic metadata, business logic, and reusability. CDS views are the modern way to define data models in SAP HANA.
Basic CDS Syntax
Fundamental CDS view definition
Simple CDS View
Basic view definition with select statement
define view ZMY_VIEW as
select from MARA {
key matnr,
mtart,
maktx,
meins
};
// With alias
define view ZMY_VIEW as
select from MARA as mara {
key mara.matnr,
mara.mtart as material_type,
mara.meins as unit
};
// From another CDS view
define view ZMY_VIEW2 as
select from ZMY_VIEW {
key matnr,
material_type
};
// Multiple tables
define view ZMY_VIEW3 as
select from MARA as m {
key m.matnr,
m.mtart,
m.meins
}
where m.mtart = 'FERT';
// Distinct values
define view ZMY_VIEW4 as
select distinct from MARA {
key mtart,
meins
};Best Practice
Always use alias (as clause) to avoid ambiguity in complex views. Use descriptive names with prefixes like Z for custom objects.
Filtering & Sorting
WHERE, GROUP BY, and ORDER BY
Where & Group By
Filter and aggregate data
// Simple WHERE clause
define view ZMY_VIEW as
select from MARA {
key matnr,
mtart,
meins
}
where mtart = 'FERT';
// Multiple conditions
define view ZMY_VIEW as
select from MARA {
key matnr,
mtart
}
where mtart = 'FERT' and meins = 'ST';
// IN condition
define view ZMY_VIEW as
select from MARA {
key matnr
}
where mtart in ('FERT', 'HALB');
// LIKE pattern
define view ZMY_VIEW as
select from MARA {
key matnr,
maktx
}
where maktx like 'Material%';
// GROUP BY aggregation
define view ZMY_STATS as
select from MARA {
mtart,
count(*) as cnt : int,
count(distinct meins) as distinct_units : int
}
group by mtart;
// ORDER BY
define view ZMY_VIEW as
select from MARA {
key matnr,
mtart,
meins
}
order by mtart asc, meins desc;
// UNION
define view ZMY_UNION as
select from MARA { matnr as id, mtart as type }
union
select from MAKT { pernr as id, mtart as type };Associations
Relationships between CDS views
One-to-One Associations
1:1 relationships
// Define association
define view ZMATERIAL as
select from MARA {
key matnr,
mtart,
meins,
// One-to-one association
association [1:1] to MAKT
on $projection.matnr = MAKT.matnr
and MAKT.spras = 'E'
as description
};
// Use association in another view
define view ZMATERIAL_EXTENDED as
select from ZMATERIAL {
key matnr,
mtart,
meins,
// Expose association
description
};
// Access association in query
select from ZMATERIAL {
matnr,
mtart,
description.maktx as description
};
// Foreign key style
define view ZUSER_WITH_ORG as
select from USR01 {
key bname,
datlo,
association [1:1] to T001
on $projection.mandt = T001.mandt
as organization
};One-to-Many Associations
1:n relationships
// One-to-many association
define view ZCUSTOMER_ORDERS as
select from KNA1 {
key kunnr,
name1,
land1,
// One-to-many association
association [1:n] to VBAK
on $projection.kunnr = VBAK.kunnr
as orders
};
// Using 1:n in query
select from ZCUSTOMER_ORDERS as cust
left outer join VBAK as ord
on cust.kunnr = ord.kunnr
{
cust.kunnr,
cust.name1,
ord.vbeln as order_id
};
// Nested associations
define view ZORDER_DETAILS as
select from VBAK {
key vbeln,
kunnr,
association [1:n] to VBAP
on $projection.vbeln = VBAP.vbeln
as items,
association [1:1] to ZCUSTOMER_ORDERS
on $projection.kunnr = ZCUSTOMER_ORDERS.kunnr
as customer
};
// Composition (strong ownership)
define view ZORDER_COMPOSITION as
select from VBAK {
key vbeln,
kunnr,
composition [1:n] of VBAP
on $projection.vbeln = VBAP.vbeln
as items
};Association Best Practice
Use associations for semantic relationships. They enable proper navigation in SAP UI5 and improve query performance through lazy loading.
Calculations & Expressions
Calculated fields and expressions
Calculated Fields
Add computed columns
// String concatenation
define view ZMY_VIEW as
select from KNA1 {
key kunnr,
concat(name1, ' ', name2) as full_name : string,
upper(city) as city_upper : string
};
// Arithmetic
define view ZMATERIAL_PRICE as
select from MARA {
key matnr,
meins,
1000 as standard_price : decimal(10,2),
standard_price * 1.19 as price_with_tax :
decimal(10,2)
};
// CAST and type conversion
define view ZMY_VIEW as
select from VBAK {
key vbeln,
cast(erdat as date) as order_date : date,
cast(netwr as decimal(13,2)) as amount :
decimal(13,2)
};
// CASE expression
define view ZORDER_STATUS as
select from VBAK {
key vbeln,
case vbtyp
when 'C' then 'Order'
when 'K' then 'Quotation'
else 'Other'
end as document_type : string
};
// Arithmetic with CASE
define view ZORDER_DISCOUNT as
select from VBAP {
key vbeln,
key posnr,
netwr,
case
when kwmeng > 100 then netwr * 0.10
when kwmeng > 50 then netwr * 0.05
else 0
end as discount_amount : decimal(13,2)
};Aggregation Functions
COUNT, SUM, AVG, MAX, MIN
Aggregate Functions
Summarize data
// COUNT aggregation
define view ZSALES_COUNT as
select from VBAK {
kunnr,
count(*) as order_count : int,
count(distinct vbeln) as distinct_orders : int,
count(vbeln) as total_lines : int
}
group by kunnr;
// SUM aggregation
define view ZSALES_TOTAL as
select from VBAK {
kunnr,
sum(netwr) as total_sales : decimal(15,2),
sum(case when vbtyp = 'C'
then netwr else 0 end)
as order_total : decimal(15,2)
}
group by kunnr;
// AVG, MAX, MIN
define view ZORDER_STATS as
select from VBAK {
kunnr,
avg(netwr) as avg_order : decimal(13,2),
max(netwr) as max_order : decimal(13,2),
min(netwr) as min_order : decimal(13,2)
}
group by kunnr;
// Multiple aggregations
define view ZCOMPLEX_STATS as
select from VBAP {
matnr,
sum(kwmeng) as total_qty : decimal(13,3),
avg(netpr) as avg_price : decimal(13,2),
count(*) as line_count : int,
max(kwmeng) as max_qty : decimal(13,3)
}
group by matnr;
// HAVING clause (filter after grouping)
define view ZACTIVE_MATERIALS as
select from VBAP {
matnr,
count(*) as sales_count : int
}
group by matnr
having count(*) > 10;Annotations
Metadata and semantic information
Common Annotations
Add meaning and configuration to views
// UI annotations
define view ZMY_VIEW
@UI.headerInfo: { typeName: 'Material', typeNamePlural: 'Materials' }
as
select from MARA {
key matnr,
mtart,
meins
};
// Metadata and labels
@EndUserText.label: 'Material Master View'
@EndUserText.description: 'Complete material information'
define view ZMY_MATERIAL as
select from MARA {
key matnr : mara.matnr
@EndUserText.label: 'Material Number',
mtart : mara.mtart
@EndUserText.label: 'Material Type',
meins : mara.meins
@EndUserText.label: 'Unit of Measure'
};
// Semantic annotations
@Semantics.systemDate.lastChangedAt: true
define view ZCUSTOMER_WITH_META as
select from KNA1 {
key kunnr,
name1,
laeda as changed_date : date
};
// Text association
define view ZCUSTOMER_VIEW as
select from KNA1 {
key kunnr,
name1 : KNA1.name1
@Semantics.text: true,
land1
};
// Currency/Quantity annotations
define view ZORDER_AMOUNTS as
select from VBAK {
key vbeln,
waerk : vbak.waerk
@Semantics.currencyCode: true,
netwr : vbak.netwr
@Semantics.amount.currencyCode: 'waerk'
};
// Access control annotation
@AccessControl.authorizationCheck: #CHECK
define view ZSENSITIVE_DATA as
select from VBAK {
key vbeln,
kunnr,
netwr
};
// Searchable and sortable
define view ZPRODUCT_VIEW as
select from MARA {
key matnr,
mtart : mara.mtart
@Search.defaultSearchElement: true
@EndUserText.label: 'Type',
maktx
@Search.defaultSearchElement: true
};Annotation Benefits
Annotations provide semantic meaning that powers SAP UI5 applications, OData services, and analytics tools. Always document your views with annotations.
Parameters & Actions
Input parameters and operations
View Parameters
Accept input parameters
// Simple parameter
define view ZMAT_BY_TYPE
(p_mtart: abap.char(4))
as
select from MARA {
key matnr,
mtart,
meins
}
where mtart = :p_mtart;
// Multiple parameters
define view ZMAT_FILTERED
(p_mtart: abap.char(4),
p_meins: abap.char(3),
p_active: abap.char(1) = 'X')
as
select from MARA {
key matnr,
mtart,
meins
}
where mtart = :p_mtart
and meins = :p_meins;
// Parameter with default
define view ZORDERS_TODAY
(p_date: abap.dats =
$session.system_date)
as
select from VBAK {
key vbeln,
erdat,
netwr
}
where erdat = :p_date;
// Using $session and $user
define view ZUSER_ORDERS
(p_user: abap.char(12) = $user.id)
as
select from VBAK {
key vbeln,
ernam,
netwr
}
where ernam = :p_user;
// Parameter in calculation
define view ZPRICED_MATERIALS
(p_currency: abap.cuky = 'USD')
as
select from MARA {
key matnr,
mtart,
cast(1000 as decimal(10,2))
as price : decimal(10,2),
:p_currency as currency : abap.cuky
};Actions & Custom Logic
Define actions on views
// Action definition (binding aware)
define view ZORDER_ACTIONS as
select from VBAK {
key vbeln,
kunnr,
vbtyp,
// Action for confirmation
@UI.hidden: true
case vbtyp
when 'C' then 'CONFIRM'
else ''
end as confirm_action : string
};
// Status-based actions
define view ZDOCUMENT_WORKFLOW as
select from VBAK {
key vbeln,
status : vbak.vbtyp,
case status
when 'DRAFT' then 'SUBMIT'
when 'SUBMITTED' then 'APPROVE'
when 'APPROVED' then 'POST'
else ''
end as next_action : string
};
// Conditional field visibility
@UI.hidden: #(processing)
define view ZCONDITIONAL_VIEW as
select from VBAK {
key vbeln,
kunnr,
case
when vbtyp = 'C' then 1
else 0
end as processing : int
};
// Virtual element (for custom actions)
define view ZORDERS_WITH_ACTIONS as
select from VBAK {
key vbeln,
kunnr,
vbtyp,
// Indicator field
case
when netwr > 10000 then 'HIGH'
when netwr > 5000 then 'MEDIUM'
else 'LOW'
end as priority : string
};Advanced CDS Features
Complex queries and patterns
Advanced Techniques
Complex CDS patterns
// Nested select with join
define view ZCOMPLEX_VIEW as
select from MARA as m
left outer join MAKT as t
on m.matnr = t.matnr
and t.spras = 'E'
left outer join MARC as c
on m.matnr = c.matnr
and c.werks = '1000'
{
key m.matnr,
m.mtart,
t.maktx as description,
c.labst as stock
};
// Subquery in SELECT
define view ZMAT_WITH_ORDERS as
select from MARA as m {
key m.matnr,
m.mtart,
(select count(*) from VBAP as v
where v.matnr = m.matnr)
as order_count : int
};
// UNION with different structures
define view ZCOMBINED_DOCS as
select from VBAK {
vbeln as doc_id,
'ORDER' as doc_type,
netwr as amount
}
union
select from VBRK {
vbeln as doc_id,
'INVOICE' as doc_type,
netwr as amount
};
// Window functions (SAP HANA 2.0+)
define view ZRANK_MATERIALS as
select from VBAP {
key vbeln,
key posnr,
matnr,
kwmeng,
rank() over (
partition by vbeln
order by kwmeng desc
) as rank : int
};
// ROW_NUMBER
define view ZROW_NUMBERED as
select from MARA {
key matnr,
mtart,
row_number() over (
order by matnr
) as row_num : int
};
// Cross join (cartesian product)
define view ZCROSS_MATERIALS as
select from MARA as m
cross join MARC as c
on m.matnr = c.matnr
{
key m.matnr,
c.werks as plant
}
where m.mtart = 'FERT';Performance Consideration
Use window functions carefully - they can be expensive. Subqueries in SELECT should filter early. Always check execution plans with HANA Studio or Cloud Studio.
Best Practices
Professional CDS development
| Practice | Description | Example |
|---|---|---|
| Use aliases | Always alias tables for clarity | select from MARA as m { m.matnr } |
| Key fields first | Define keys at the beginning | key matnr, key posnr, |
| Explicit casting | Cast to target types | cast(field as type) |
| Name conventions | Use prefixes and suffixes | Z_MATERIAL_V for views |
| Associations | Use for relationships | association [1:1] to MAKT |
| Annotations | Document all fields | @EndUserText.label |
| Reduce data early | Filter at lowest level | where clause in base view |
| Reuse views | Build on existing views | select from existing_view |
| Avoid SELECT * | Explicitly list fields | select from MARA { field1, field2 } |
| Partition key | Design for parallel processing | partition by key_field |
| Index awareness | Consider DB indexes | join on indexed columns |
| Document purpose | Clear descriptions | @EndUserText.description |
Naming Conventions:
// View naming
Z_CUSTOMER_V // Base view suffix _V
Z_CUSTOMER_ORDERS_V // Descriptive names
Z_CUSTOMER_STAT_V // Purpose clear
// Field naming
define view ZCUSTOMER_V as
select from KNA1 {
key kunnr, // Clear name
name1 as customer_name : string,
land1 as country : string,
erdat as created_date : date,
aedat as changed_date : date
};
// Hierarchy
// Base views (transactional data)
Z_CUSTOMER_V
Z_ORDER_V
// Extended views (with enrichment)
Z_CUSTOMER_EXTENDED_V
Z_ORDER_WITH_DETAILS_V
// Calculated views (aggregations)
Z_CUSTOMER_STATS_V
Z_SALES_SUMMARY_VPerformance Tips:
// ✓ Good: Filter early
define view ZACTIVE_MAT as
select from MARA {
key matnr
}
where mtart = 'FERT' // Filter here
and meins = 'ST';
// ✗ Avoid: Filtering in application
// Application does: WHERE mtart = 'FERT'
// ✓ Good: Use associations
select from ZCUSTOMER_V {
kunnr,
customer.name1 // Lazy loaded
};
// ✗ Avoid: Multiple joins
select from KNA1 join VBAK ...
// ✓ Good: Projections
select from ZCUSTOMER_V {
kunnr, name1 // Only needed fields
};
// ✗ Bad: Expose all
select from ZCUSTOMER_V { * };Common Patterns
Reusable CDS patterns
Master Data View
Typical master data pattern
@EndUserText.label: 'Material Master'
@EndUserText.description: 'Complete material information'
define view ZMATERIAL_V as
select from MARA as m
left outer join MAKT as t
on m.matnr = t.matnr
and t.spras = 'E'
left outer join MARC as c
on m.matnr = c.matnr
and c.werks = '1000'
{
key m.matnr,
m.mtart : mara.mtart
@EndUserText.label: 'Type',
t.maktx : makt.maktx
@EndUserText.label: 'Description',
c.labst : marc.labst
@EndUserText.label: 'Stock'
}
where m.mtart in ('FERT', 'HALB');Aggregation View
Summary/statistics pattern
define view ZSALES_SUMMARY_V as
select from VBAP {
kunnr,
matnr,
sum(kwmeng) as total_qty : decimal(13,3),
sum(netwr) as total_amount : decimal(15,2),
count(*) as line_count : int,
avg(netpr) as avg_price : decimal(13,2)
}
group by kunnr, matnr
having count(*) > 0
order by total_amount desc;Hierarchy View
Master detail relationship
define view ZORDER_HIERARCHY_V as
select from VBAK {
key vbeln,
kunnr,
erdat,
association [1:n] to VBAP
on $projection.vbeln = VBAP.vbeln
as items,
association [1:1] to ZCUSTOMER_V
on $projection.kunnr = ZCUSTOMER_V.kunnr
as customer
}
where vbtyp = 'C';Status View
Workflow/status pattern
define view ZDOCUMENT_STATUS_V as
select from VBAK {
key vbeln,
case vbtyp
when 'C' then 'ORDER'
when 'K' then 'QUOTATION'
else 'OTHER'
end as doc_type : string,
case
when vbtyp = 'C' then 'ACTIVE'
else 'INACTIVE'
end as status : string
};Data Types & Conversions
ABAP type mappings in CDS
Common ABAP Types in CDS
Type definitions and conversions
// Text types
define view ZTYPE_DEMO as
select from MARA {
key matnr : abap.char(18), // Character
maktx : abap.string, // String
meins : abap.unit // Unit
};
// Numeric types
define view ZCALC_TYPES as
select from VBAP {
key vbeln : abap.char(10),
kwmeng : abap.quan(13,3), // Quantity
netpr : abap.curr(13,2), // Currency
percentage : abap.dec(5,2), // Decimal
counter : abap.int4 // Integer
};
// Date and Time
define view ZDATE_DEMO as
select from VBAK {
key vbeln,
erdat : abap.dats, // Date
erzet : abap.tims, // Time
created : abap.utclong // Timestamp
};
// Boolean and flags
define view ZFLAG_DEMO as
select from MARA {
key matnr,
case
when mtart = 'FERT' then 'X'
else ''
end as is_finished : abap.char(1)
};
// Currency and quantity codes
@Semantics.currencyCode: true
define view ZCURR_DEMO as
select from VBAK {
key vbeln,
waerk : abap.cuky, // Currency code
netwr : abap.curr(13,2)
};
// Casting examples
define view ZCAST_DEMO as
select from MARA {
key matnr,
cast(matnr as abap.string) as str_matnr :
abap.string,
cast(1000.50 as abap.dec(13,2)) as price :
abap.dec(13,2),
cast('20240118' as abap.dats) as date_field :
abap.dats
};Performance & Optimization
Optimize CDS view execution
| Issue | Problem | Solution |
|---|---|---|
| Large result set | Memory consumption, slow execution | Add WHERE clause, use LIMIT |
| Multiple joins | Complex execution plan | Use associations instead |
| Subqueries | Multiple passes through data | Join parent data or filter early |
| SELECT * | Unnecessary columns | Explicitly list needed fields |
| No indexes | Full table scan | Design keys for DB indexes |
| Wrong join type | Extra rows processed | Use LEFT/INNER correctly |
| Late filtering | Process unnecessary data | Filter at lowest level |
| Missing associations | Redundant joins | Use associations for relationships |
| Window functions | Expensive computations | Only on pre-filtered data |
| Type mismatches | Implicit conversions | Use correct types upfront |
Debugging Performance
Use SAP HANA Studio → SQL Plan to analyze execution. Check for full table scans and missing indexes. Monitor view compilation in log files.
Common Pitfalls & Solutions
Avoid these CDS mistakes
| Pitfall | Problem | Solution |
|---|---|---|
| Circular associations | Can't compile views | Reorganize view hierarchy |
| Missing key fields | Can't modify data in UI | Always define primary keys |
| SELECT * | Breaks if source changes | Explicit field list |
| Type conflicts | Implicit conversion errors | Use explicit CAST |
| Wrong associations | Returns wrong data | Verify association conditions |
| No CASE ELSE | NULL values returned | Add ELSE clause in CASE |
| Parameter type mismatch | Runtime errors | Match types exactly |
| Ambiguous aliases | Duplicate column names | Always use alias.field |
| Missing WHERE keys | Wrong filter behavior | Include all key conditions |
| Performance regression | Query got slow | Check execution plan, reindex |
Migration from SQL Views
Converting traditional SQL views to CDS
Traditional SQL → CDS:
-- Old SQL View
CREATE VIEW V_MATERIAL AS
SELECT m.matnr, m.mtart, t.maktx
FROM MARA m
LEFT JOIN MAKT t
ON m.matnr = t.matnr
AND t.spras = 'E'
WHERE m.mtart = 'FERT';
↓
// New CDS View
define view Z_MATERIAL_V as
select from MARA as m
left outer join MAKT as t
on m.matnr = t.matnr
and t.spras = 'E'
{
key m.matnr,
m.mtart,
t.maktx as description
}
where m.mtart = 'FERT';Migration Benefits:
- Better integration with SAP UI5
- OData service generation
- Analytics integration
- Semantic metadata support
- Easier maintainability
- Better performance (smart execution)
- Built-in security support
- Associations and compositions
- Calculated fields
- Parameter support
Migration Path
Plan migration in phases. Run old and new views in parallel. Test thoroughly before cutover.
Debugging & Troubleshooting
Diagnose CDS issues
Debugging Techniques
Tools and methods for troubleshooting
// Test view with parameters
select * from Z_MATERIAL_V(p_mtart => 'FERT')
where rownum <= 10;
// Check compilation errors
// HANA Studio → SQLScript → Right-click view → Check syntax
// Debug view definition
// SELECT * FROM SYS.VIEWS
// WHERE VIEW_NAME = 'Z_MATERIAL_V';
// Check association navigation
select from Z_ORDER_HIERARCHY_V {
vbeln,
kunnr,
items.posnr, // Navigate association
items.matnr
} where vbeln = '0000123456';
// Monitor performance
// HANA Studio → SQL Analyzer → Paste query → Analyze
// Check execution plan
EXPLAIN SELECT * FROM Z_MATERIAL_V
WHERE mtart = 'FERT';
// View execution statistics
// HANA Cockpit → SQL Statements → Find view query
// Debug type issues
// Check field types at definition point
// Hover in Studio to see inferred types
// Test expressions
// Create test view with calculation
define view Z_TEST_CALC as
select from MARA {
key matnr,
cast(1000 as decimal(10,2)) * 1.19 as result
};
// Enable debug output (development only)
set option connection_context = 'DEBUG_MODE=ON';
// View dependencies
// HANA Studio → Repository → View dependencies graph
// Check for circular references
// HANA Studio → Editors → Validate CDS modelPro Debugging
Use SAP HANA Studio's SQL Editor to test queries before implementing views. Always check the execution plan for large queries.
Additional Resources
For more HANA learning resources, visit our SAP HANA Documentation and explore CDS Views Deep Dive Module.