Vues CDS ABAP : Comprendre et utiliser les Core Data Services

Catégorie
ABAP-Statements
Publié
Auteur
Johannes

Les vues CDS (Core Data Services) sont la manière moderne de définir des modèles de données dans SAP. Elles permettent des définitions de données sémantiquement riches et réutilisables directement au niveau de la base de données avec une optimisation push-down pour HANA.

Que sont les vues CDS ?

Les vues CDS sont :

  • Extensions SQL déclaratives pour la modélisation sémantique de données
  • Vues de base de données avec des fonctionnalités étendues (annotations, associations)
  • Fondation pour SAP Fiori, RAP et le développement SAP moderne
  • Performantes grâce au push-down vers la base de données (HANA)

Syntaxe de base

@AbapCatalog.sqlViewName: 'ZSQL_VIEW_NAME"
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Description de la vue"
define view Z_CDS_VIEW_NAME
as select from <source_donnees>
{
<liste_champs>
}

Exemples

1. Vue CDS simple

@AbapCatalog.sqlViewName: 'ZSQLCUSTOMERS"
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Données de base clients"
define view Z_I_Customers
as select from kna1
{
key kunnr as CustomerId,
name1 as CustomerName,
ort01 as City,
land1 as Country,
erdat as CreatedDate
}

2. Utiliser une vue CDS en ABAP

" Utiliser la vue CDS comme une table
SELECT * FROM z_i_customers
INTO TABLE @DATA(lt_customers)
WHERE country = 'DE'.
LOOP AT lt_customers INTO DATA(ls_customer).
WRITE: / ls_customer-customerid, ls_customer-customername.
ENDLOOP.
" Avec déclaration inline
SELECT customerid, customername, city
FROM z_i_customers
WHERE country = 'DE"
INTO TABLE @DATA(lt_german_customers).

3. Vue CDS avec JOIN

@AbapCatalog.sqlViewName: 'ZSQLORDERCUST"
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Commandes avec données client"
define view Z_I_OrdersWithCustomer
as select from vbak as order
inner join kna1 as customer
on order.kunnr = customer.kunnr
{
key order.vbeln as OrderNumber,
order.erdat as OrderDate,
order.netwr as NetValue,
order.waerk as Currency,
customer.kunnr as CustomerId,
customer.name1 as CustomerName,
customer.ort01 as CustomerCity
}

4. LEFT OUTER JOIN

define view Z_I_CustomersWithOrders
as select from kna1 as customer
left outer join vbak as order
on customer.kunnr = order.kunnr
{
key customer.kunnr as CustomerId,
customer.name1 as CustomerName,
order.vbeln as OrderNumber,
order.netwr as OrderValue
}

5. Champs calculés (Calculated Fields)

@AbapCatalog.sqlViewName: 'ZSQLORDERCALC"
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Commandes avec calculs"
define view Z_I_OrderCalculations
as select from vbak
{
key vbeln as OrderNumber,
netwr as NetValue,
waerk as Currency,
// Calculs
netwr * 1.19 as GrossValue,
// Conditions avec CASE
case
when netwr >= 10000 then 'HIGH"
when netwr >= 1000 then 'MEDIUM"
else 'LOW"
end as ValueCategory,
// Fonctions de date
dats_days_between( erdat, $session.system_date ) as DaysSinceOrder
}

6. Agrégations

@AbapCatalog.sqlViewName: 'ZSQLCUSTTOTAL"
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Chiffre d''affaires client agrégé"
define view Z_I_CustomerTotals
as select from vbak
{
key kunnr as CustomerId,
// Fonctions d'agrégation
sum( netwr ) as TotalOrderValue,
count(*) as OrderCount,
avg( netwr ) as AverageOrderValue,
min( erdat ) as FirstOrderDate,
max( erdat ) as LastOrderDate
}
group by kunnr

7. Associations

@AbapCatalog.sqlViewName: 'ZSQLORDERASSOC"
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Commandes avec associations"
define view Z_I_Orders
as select from vbak as Order
association [1..1] to kna1 as _Customer
on $projection.CustomerId = _Customer.kunnr
association [0..*] to vbap as _Items
on $projection.OrderNumber = _Items.vbeln
{
key vbeln as OrderNumber,
kunnr as CustomerId,
erdat as OrderDate,
netwr as NetValue,
// Exposer les associations
_Customer,
_Items
}

8. Utiliser les associations en ABAP

" Utiliser les expressions de chemin
SELECT OrderNumber,
OrderDate,
NetValue,
\_Customer-name1 as CustomerName,
\_Customer-ort01 as CustomerCity
FROM z_i_orders
INTO TABLE @DATA(lt_orders_with_customer).
" Avec WHERE sur l'association
SELECT *
FROM z_i_orders
WHERE \_Customer-land1 = 'DE"
INTO TABLE @DATA(lt_german_orders).

9. Paramètres dans les vues CDS

@AbapCatalog.sqlViewName: 'ZSQLORDERPARAM"
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Commandes avec paramètre"
define view Z_I_OrdersByDate
with parameters
p_from_date : abap.dats,
p_to_date : abap.dats
as select from vbak
{
key vbeln as OrderNumber,
erdat as OrderDate,
netwr as NetValue,
kunnr as CustomerId
}
where erdat >= $parameters.p_from_date
and erdat <= $parameters.p_to_date

10. Vue paramétrée en ABAP

" Passer les paramètres
SELECT *
FROM z_i_ordersbydate( p_from_date = '20240101',
p_to_date = '20241231' )
INTO TABLE @DATA(lt_orders_2024).
" Avec des variables
DATA: lv_from TYPE d VALUE '20240101',
lv_to TYPE d VALUE '20241231'.
SELECT *
FROM z_i_ordersbydate( p_from_date = @lv_from,
p_to_date = @lv_to )
INTO TABLE @DATA(lt_orders).

11. Annotations pour l’UI (Fiori)

@AbapCatalog.sqlViewName: 'ZSQLCUSTUI"
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Clients pour UI"
@UI.headerInfo: {
typeName: 'Client',
typeNamePlural: 'Clients',
title: { value: 'CustomerName' }
}
define view Z_C_Customers
as select from z_i_customers
{
@UI.facet: [{ position: 10, type: #IDENTIFICATION_REFERENCE }]
key @UI.lineItem: [{ position: 10 }]
@UI.identification: [{ position: 10 }]
CustomerId,
@UI.lineItem: [{ position: 20 }]
@UI.identification: [{ position: 20 }]
@UI.selectionField: [{ position: 10 }]
CustomerName,
@UI.lineItem: [{ position: 30 }]
@UI.selectionField: [{ position: 20 }]
City,
@UI.lineItem: [{ position: 40 }]
Country
}

12. Access Control (DCL)

@EndUserText.label: 'Contrôle d''accès pour les clients"
@MappingRole: true
define role Z_I_Customers_Role {
grant select on Z_I_Customers
where Country = aspect pfcg_auth( ZAUTH_OBJ, ZLAND, ACTVT = '03' );
}

13. UNION et UNION ALL

define view Z_I_AllPartners
as select from kna1
{
key kunnr as PartnerId,
name1 as PartnerName,
'CUSTOMER' as PartnerType
}
union all
select from lfa1
{
key lifnr as PartnerId,
name1 as PartnerName,
'SUPPLIER' as PartnerType
}

14. CDS Table Functions (AMDP)

@EndUserText.label: 'CDS Table Function"
define table function Z_TF_ComplexLogic
with parameters
p_date : abap.dats
returns {
key OrderId : abap.char(10);
Amount : abap.curr(15,2);
Status : abap.char(1);
}
implemented by method
zcl_complex_logic=>get_orders;
CLASS zcl_complex_logic DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES if_amdp_marker_hdb.
CLASS-METHODS get_orders
FOR TABLE FUNCTION z_tf_complexlogic.
ENDCLASS.
CLASS zcl_complex_logic IMPLEMENTATION.
METHOD get_orders BY DATABASE FUNCTION FOR HDB
LANGUAGE SQLSCRIPT OPTIONS READ-ONLY
USING vbak.
RETURN SELECT vbeln as orderid,
netwr as amount,
'A' as status
FROM vbak
WHERE erdat = :p_date;
ENDMETHOD.
ENDCLASS.

15. Extend Views

@AbapCatalog.sqlViewAppendName: 'ZSQLCUSTEXT"
@EndUserText.label: 'Extension pour les clients"
extend view Z_I_Customers with Z_E_Customers_Extension
{
// Champs supplémentaires d'autres tables
kna1.brsch as Industry,
kna1.kukla as CustomerClass
}

Types de vues CDS

TypePréfixeObjectif
Interface ViewI_ ou Z_I_Modèle de données de base, réutilisable
Consumption ViewC_ ou Z_C_Spécifique UI, avec annotations UI
Basic ViewR_ ou Z_R_Restreint, pour usage interne
Extension ViewE_ ou Z_E_Extensions de vues existantes

Annotations importantes

// Annotations de catalogue
@AbapCatalog.sqlViewName: 'SQL_NAME' // Nom de la vue SQL (max 16 caractères)
@AbapCatalog.compiler.compareFilter: true // Optimisation des filtres
@AbapCatalog.preserveKey: true // Conserver la clé
@AbapCatalog.buffering.status: #ACTIVE // Activer le buffering
// Contrôle d'accès
@AccessControl.authorizationCheck: #CHECK // Vérification des autorisations
@AccessControl.authorizationCheck: #NOT_REQUIRED
// Métadonnées
@EndUserText.label: 'Description"
@ObjectModel.representativeKey: 'FieldName"
@ObjectModel.semanticKey: ['Field1', 'Field2']
// Analytics
@Analytics.dataCategory: #CUBE
@Analytics.dataCategory: #DIMENSION
// OData/Fiori
@OData.publish: true
@UI.headerInfo.typeName: 'Entity"

Fonctions CDS

// Fonctions de chaîne
concat( field1, field2 )
substring( field, position, length )
length( field )
upper( field )
lower( field )
ltrim( field, char )
rtrim( field, char )
// Fonctions numériques
abs( field )
ceil( field )
floor( field )
round( field, decimals )
div( field1, field2 )
mod( field1, field2 )
// Fonctions date/heure
dats_days_between( date1, date2 )
dats_add_days( date, days )
dats_add_months( date, months )
$session.system_date
$session.user
$session.client
// Conversions
cast( field as type )
currency_conversion( ... )
unit_conversion( ... )
// Gestion des nulls
coalesce( field, default )

Bonnes pratiques

// 1. Noms de champs explicites (CamelCase)
@AbapCatalog.sqlViewName: 'ZSQLSALES"
define view Z_I_SalesOrders
as select from vbak
{
key vbeln as SalesOrderId, // Pas : VBELN
kunnr as CustomerId, // Pas : KUNNR
erdat as CreationDate // Pas : ERDAT
}
// 2. Annotations pour la sémantique
{
@Semantics.amount.currencyCode: 'Currency"
netwr as NetAmount,
@Semantics.currencyCode: true
waerk as Currency,
@Semantics.quantity.unitOfMeasure: 'Unit"
kwmeng as Quantity,
@Semantics.unitOfMeasure: true
vrkme as Unit
}
// 3. Cardinalités pour les associations
association [1..1] to ... // Exactement une
association [0..1] to ... // Zéro ou une
association [0..*] to ... // Zéro à plusieurs
association [1..*] to ... // Une à plusieurs

Remarques importantes / Bonnes pratiques

  • Les vues CDS sont la fondation du développement SAP moderne (Fiori, RAP).
  • Utilisez les Interface Views (I_) pour les modèles de base réutilisables.
  • Utilisez les Consumption Views (C_) pour les besoins spécifiques à l’UI.
  • Associations plutôt que JOINs pour des requêtes plus flexibles et performantes.
  • Les Annotations contrôlent le comportement, l’UI et les autorisations.
  • Activez @AccessControl.authorizationCheck pour la vérification des autorisations.
  • Les vues CDS peuvent être utilisées comme des tables normales en ABAP dans SELECT.
  • Optimisation HANA : Les calculs sont poussés vers la base de données.
  • Utilisez les Paramètres pour des vues flexibles et réutilisables.
  • Virtual Data Model (VDM) : Suivez les conventions de nommage SAP pour des modèles cohérents.