Tables dans ABAP Cloud : De SE11 à la définition basée sur CDS

Catégorie
ABAP Cloud
Publié
Auteur
Johannes

En ABAP classique, SE11 était l’outil central pour les définitions de tables. Dans ABAP Cloud, c’est différent : les tables sont définies directement dans le code en tant que DDL Source, activées via les ABAP Development Tools (ADT). Cet article montre la transition du monde classique SE11 vers la définition de tables moderne basée sur CDS.

Le problème : SE11 dans ABAP Cloud ?

Celui qui cherche une transaction SE11 dans ABAP Cloud ne la trouvera pas :

SE11? → N'existe pas dans ABAP Cloud
SE16? → N'existe pas dans ABAP Cloud
SM30? → N'existe pas dans ABAP Cloud

Toutes les définitions de données se font via ADT (Eclipse) et les fichiers DDL Source.

Comparaison des définitions de tables

ABAP classique (SE11)

Transaction SE11 → Table de base de données → ZFLIGHT_BOOK
Champs:
MANDT CLNT Mandant
BOOKING_ID NUMC(10) Numéro de réservation
FLIGHT_ID NUMC(10) Numéro de vol
CUSTOMER_ID NUMC(10) Numéro de client
BOOKING_DATE DATS Date de réservation
PRICE CURR(15,2) Prix
CURRENCY CUKY Devise
STATUS CHAR(1) Statut
→ Activer → Table de base de données créée

ABAP Cloud (DDL Source)

@EndUserText.label: 'Réservations de vols"
@AbapCatalog.enhancement.category: #NOT_EXTENSIBLE
@AbapCatalog.tableCategory: #TRANSPARENT
@AbapCatalog.deliveryClass: #A
@AbapCatalog.dataMaintenance: #RESTRICTED
define table zflight_book {
key client : abap.clnt not null;
key booking_id : abap.numc(10) not null;
flight_id : abap.numc(10);
customer_id : abap.numc(10);
booking_date : abap.dats;
@Semantics.amount.currencyCode: 'zflight_book.currency_code"
price : abap.curr(15,2);
currency_code: abap.cuky;
status : abap.char(1);
}

Avantages de la syntaxe DDL :

  • Versionnable avec Git (voir abapGit)
  • Pas de dépendance GUI
  • Annotations directement sur le champ
  • Meilleure lisibilité en revue de code

Créer une table dans ADT

Étape par étape

1. Clic droit sur le paquet → New → Other ABAP Repository Object
2. Dictionary → Database Table
3. Entrer le nom : ZFLIGHT_BOOK
4. Description : Réservations de vols
5. Finish → Le DDL Source est généré

Structure de base d’une table

@EndUserText.label: 'Description de la table"
@AbapCatalog.enhancement.category: #NOT_EXTENSIBLE
@AbapCatalog.tableCategory: #TRANSPARENT
@AbapCatalog.deliveryClass: #A
@AbapCatalog.dataMaintenance: #RESTRICTED
define table ztable {
key client : abap.clnt not null;
key key_field : <type_donnees> not null;
field1 : <type_donnees>;
field2 : <type_donnees>;
}

Annotations importantes

AnnotationSignificationValeurs
@AbapCatalog.tableCategoryType de table#TRANSPARENT, #STRUCTURE
@AbapCatalog.deliveryClassClasse de livraison#A (données application), #C (customizing)
@AbapCatalog.dataMaintenanceAutorisation de maintenance#RESTRICTED, #ALLOWED
@AbapCatalog.enhancement.categoryExtensibilité#NOT_EXTENSIBLE, #EXTENSIBLE_ANY

Types de données intégrés dans ABAP Cloud

Dans ABAP Cloud, les types de données sont référencés directement avec abap.<type> :

Types fréquemment utilisés

" Chaînes de caractères
field_char : abap.char(30); " Longueur fixe
field_string : abap.string(256); " Longueur variable
field_numc : abap.numc(10); " Texte numérique (ex. IDs)
field_lang : abap.lang; " Clé de langue
" Nombres
field_int : abap.int4; " Integer (4 octets)
field_int8 : abap.int8; " Integer (8 octets)
field_dec : abap.dec(10,2); " Nombre décimal
field_curr : abap.curr(15,2); " Montant en devise
field_quan : abap.quan(13,3); " Champ de quantité
" Date et heure
field_date : abap.dats; " Date (AAAAMMJJ)
field_time : abap.tims; " Heure (HHMMSS)
field_tstmp : abap.utclong; " Horodatage UTC (recommandé !)
" Divers
field_bool : abap_boolean; " Booléen (X ou vide)
field_client : abap.clnt; " Mandant
field_cuky : abap.cuky; " Code devise
field_unit : abap.unit(3); " Unité de mesure

Horodatage : Préférer UTCLONG

" Ancien : Date et heure séparées
created_date : abap.dats;
created_time : abap.tims;
" Nouveau : Horodatage UTC
created_at : abap.utclong;
changed_at : abap.utclong;

Le type abap.utclong stocke les horodatages indépendamment du fuseau horaire et est le standard pour ABAP Cloud.

Éléments de données et domaines

ABAP classique : Objets séparés

SE11 → Domaine → ZBOOKING_STATUS
Type de données: CHAR(1)
Plage de valeurs: O (Open), C (Confirmed), X (Cancelled)
SE11 → Élément de données → ZBOOKING_STATUS
Domaine: ZBOOKING_STATUS
Libellé de champ: Statut de réservation
SE11 → Table → ZFLIGHT_BOOK
STATUS → Élément de données ZBOOKING_STATUS

ABAP Cloud : Définition intégrée

Dans ABAP Cloud, les éléments de données sont définis comme DDL Source :

@EndUserText.label: 'Statut de réservation"
@EndUserText.heading: 'Statut"
define type zbooking_status : abap.char(1)

Domaine avec valeurs fixes

Pour les ensembles de valeurs fixes, il existe le concept d’Enumeration :

" Enumération pour le statut de réservation
CLASS zcl_booking_status DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES:
BEGIN OF ENUM booking_status,
open VALUE IS INITIAL,
confirmed,
cancelled,
END OF ENUM booking_status.
ENDCLASS.

Ou directement comme type CDS :

@EndUserText.label: 'Statut de réservation"
define type zbooking_status : abap.char(1)
enum {
open = 'O';
confirmed = 'C';
cancelled = 'X';
}

Exemple complet de réservation de vols

Table principale : Réservations

@EndUserText.label: 'Réservations de vols"
@AbapCatalog.enhancement.category: #NOT_EXTENSIBLE
@AbapCatalog.tableCategory: #TRANSPARENT
@AbapCatalog.deliveryClass: #A
@AbapCatalog.dataMaintenance: #RESTRICTED
define table zflight_book {
key client : abap.clnt not null;
key booking_id : abap.numc(10) not null;
" Clés métier
flight_id : abap.numc(10);
customer_id : abap.numc(10);
" Données de réservation
booking_date : abap.dats;
@Semantics.amount.currencyCode: 'zflight_book.currency_code"
price : abap.curr(15,2);
currency_code : abap.cuky;
seats_booked : abap.int4;
booking_status : abap.char(1);
" Champs administratifs
created_by : abap.uname;
created_at : abap.utclong;
last_changed_by : abap.uname;
last_changed_at : abap.utclong;
local_last_changed: abap.utclong;
}

Table de données de base : Vols

@EndUserText.label: 'Données de vol"
@AbapCatalog.enhancement.category: #NOT_EXTENSIBLE
@AbapCatalog.tableCategory: #TRANSPARENT
@AbapCatalog.deliveryClass: #A
@AbapCatalog.dataMaintenance: #RESTRICTED
define table zflight {
key client : abap.clnt not null;
key flight_id : abap.numc(10) not null;
" Données de vol
carrier_id : abap.char(3);
connection_id : abap.numc(4);
flight_date : abap.dats;
" Trajet
departure_city : abap.char(30);
departure_code : abap.char(3);
arrival_city : abap.char(30);
arrival_code : abap.char(3);
" Capacité
seats_max : abap.int4;
seats_occupied : abap.int4;
" Prix
@Semantics.amount.currencyCode: 'zflight.currency_code"
base_price : abap.curr(15,2);
currency_code : abap.cuky;
}

Table de données de base : Clients

@EndUserText.label: 'Données de base clients"
@AbapCatalog.enhancement.category: #NOT_EXTENSIBLE
@AbapCatalog.tableCategory: #TRANSPARENT
@AbapCatalog.deliveryClass: #A
@AbapCatalog.dataMaintenance: #RESTRICTED
define table zcustomer {
key client : abap.clnt not null;
key customer_id : abap.numc(10) not null;
" Données client
first_name : abap.char(40);
last_name : abap.char(40);
email : abap.char(100);
phone : abap.char(30);
" Adresse
street : abap.char(60);
city : abap.char(40);
postal_code : abap.char(10);
country : abap.char(3);
}

Table Entities : La nouvelle architecture

Avec ABAP Cloud 2024, le concept de Table Entities a été introduit. La table elle-même devient l’entité - sans CDS View supplémentaire.

Approche classique (trois objets)

1. Table de base de données (ZFLIGHT_BOOK)
2. CDS View (ZI_FlightBooking)
3. Behavior Definition (ZI_FlightBooking)

Approche Table Entity (deux objets)

1. Table Entity (ZI_FlightBooking) - Table + View en un
2. Behavior Definition (ZI_FlightBooking)

Définition de Table Entity

@EndUserText.label: 'Réservation de vol (Table Entity)"
@AbapCatalog.enhancement.category: #NOT_EXTENSIBLE
define table entity zi_flightbooking {
key client : abap.clnt not null;
key booking_id : abap.numc(10) not null;
flight_id : abap.numc(10);
customer_id : abap.numc(10);
booking_date : abap.dats;
@Semantics.amount.currencyCode: 'zi_flightbooking.currency_code"
price : abap.curr(15,2);
currency_code : abap.cuky;
booking_status : abap.char(1);
created_by : abap.uname;
created_at : abap.utclong;
last_changed_by : abap.uname;
last_changed_at : abap.utclong;
local_last_changed: abap.utclong;
}

Comparaison : Table vs Table Entity

AspectTable + CDS ViewTable Entity
Objets2 (Table + View)1
MaintenanceDouble maintenanceDéfinir une fois
FlexibilitéHauteLimitée
AliasLibrement choisisNom de champ = Nom de colonne
Champs calculésOuiNon
Recommandé pourModèles complexesCRUD simple

Plus d’informations sur le pattern CDS dans le prochain article sur les patterns RAP CDS.

Clés étrangères et associations

Clé étrangère dans la définition de table

Dans ABAP Cloud, les clés étrangères sont définies via des annotations :

@EndUserText.label: 'Réservations de vols avec clés étrangères"
define table zflight_book_fk {
key client : abap.clnt not null;
key booking_id : abap.numc(10) not null;
@AbapCatalog.foreignKey.screenCheck: false
flight_id : abap.numc(10)
with foreign key zflight
where client = zflight_book_fk.client
and flight_id = zflight_book_fk.flight_id;
@AbapCatalog.foreignKey.screenCheck: false
customer_id : abap.numc(10)
with foreign key zcustomer
where client = zflight_book_fk.client
and customer_id = zflight_book_fk.customer_id;
" ... autres champs
}

Associations dans les CDS Views

Pour les applications RAP, les associations dans la CDS View sont la meilleure approche :

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Réservations de vols avec associations"
define root view entity ZI_FlightBooking
as select from zflight_book as Booking
association [1..1] to ZI_Flight as _Flight
on $projection.FlightId = _Flight.FlightId
association [1..1] to ZI_Customer as _Customer
on $projection.CustomerId = _Customer.CustomerId
{
key Booking.booking_id as BookingId,
Booking.flight_id as FlightId,
Booking.customer_id as CustomerId,
Booking.booking_date as BookingDate,
@Semantics.amount.currencyCode: 'CurrencyCode"
Booking.price as Price,
Booking.currency_code as CurrencyCode,
Booking.booking_status as BookingStatus,
" Exposer les associations
_Flight,
_Customer
}

Cardinalités

CardinalitéSignificationExemple
[0..1]Optionnel, max. 1Contact optionnel
[1..1]Exactement 1Réservation → Vol
[0..*]Optionnel, plusieursClient → Réservations
[1..*]Au moins 1, plusieursCommande → Positions

Remplir et lire des tables

Insérer des données

" Enregistrement unique
INSERT INTO zflight_book VALUES @(
VALUE #(
client = sy-mandt
booking_id = '0000000001"
flight_id = '0000000100"
customer_id = '0000000001"
booking_date = cl_abap_context_info=>get_system_date( )
price = '499.00"
currency_code = 'EUR"
booking_status = 'O"
created_by = cl_abap_context_info=>get_user_technical_name( )
created_at = utclong_current( )
)
).
" Plusieurs enregistrements
DATA(lt_bookings) = VALUE #(
( client = sy-mandt booking_id = '0000000002' flight_id = '0000000101' ... )
( client = sy-mandt booking_id = '0000000003' flight_id = '0000000102' ... )
).
INSERT zflight_book FROM TABLE @lt_bookings.

Lire des données

" Lire via CDS View (recommandé pour RAP)
SELECT FROM ZI_FlightBooking
FIELDS BookingId, FlightId, BookingDate, Price
WHERE BookingStatus = 'O"
INTO TABLE @DATA(lt_open_bookings).
" Avec associations
SELECT FROM ZI_FlightBooking AS Booking
FIELDS Booking~BookingId,
\_Flight-DepartureCity,
\_Flight-ArrivalCity,
\_Customer-LastName
INTO TABLE @DATA(lt_with_details).

Bonnes pratiques

1. Toujours prévoir des champs administratifs

" Ces champs devraient être dans chaque table :
created_by : abap.uname;
created_at : abap.utclong;
last_changed_by : abap.uname;
last_changed_at : abap.utclong;
local_last_changed: abap.utclong; " Pour ETag/Verrouillage optimiste

2. Utiliser des annotations sémantiques

" Annoter correctement les champs de devise
@Semantics.amount.currencyCode: 'currency_code"
price : abap.curr(15,2);
currency_code : abap.cuky;
" Annoter correctement les champs de quantité
@Semantics.quantity.unitOfMeasure: 'unit"
quantity : abap.quan(13,3);
unit : abap.unit(3);

3. Respecter les conventions de nommage

Tables: z<domaine>_<nom> → zflight_book
Table Entities: zi_<nom> → zi_flightbooking
CDS Views: ZI_<Nom> (Interface) → ZI_FlightBooking
ZC_<Nom> (Consumption) → ZC_FlightBooking

4. UTCLONG au lieu de DATS/TIMS

" À éviter :
changed_date : abap.dats;
changed_time : abap.tims;
" À préférer :
changed_at : abap.utclong;

Conclusion

Les tables dans ABAP Cloud sont définies exclusivement via DDL Source dans ADT :

Classique (SE11)ABAP Cloud (ADT)
Basé sur GUIBasé sur code
Domaine → Élément de données → TableTypes inline ou en tant que Type
Dialogue clé étrangèreAnnotation clé étrangère
Non versionnablePrêt pour Git

La transition nécessite une période d’apprentissage au début, mais offre des avantages clairs : meilleure lisibilité, contrôle de version et intégration avec la pile RAP.

Pour les prochaines étapes avec RAP, voir Fondamentaux RAP, pour les CDS Views en détail CDS Views et pour la migration d’objets existants le Guide de migration ABAP Cloud.