Les requêtes SQL
Définition
La définition d’une table interne, faisant référence à un objet du dictionnaire de données (DDIC), a été développée, il reste maintenant à voir comment importer les données de la base de données et pour cela, SAP utilise le langage SQL.
Le SQL (signifiant Structured Query Language - requête de langage structurée en français) est tout simplement le langage de programmation permettant d’accéder et de gérer les données des bases de données (ajout, modification ou suppression). Pour SAP, il a été adapté en un ensemble d’opérations ABAP appelé OpenSQL. Pour schématiser, le traitement des données ressemblerait à ceci :
Une application ABAP exécute une requête SQL. Il s’agit d’une opération permettant de traiter directement avec la base de données, comme par exemple la lecture d’une table, qui sera alors envoyée en OpenSQL à une interface. Celle-ci la traduira ensuite en Native SQL (langage SQL adapté pour les bases de données) afin de consulter la base, et d’importer les informations nécessaires. Elles seront enfin retournées via l’interface à l’application ABAP qui pourra poursuivre son traitement.
Comme vu dans le chapitre Dictionnaire de données...
SELECT
SELECT result
FROM source
[[FOR ALL ENTRIES IN itab] WHERE sql_cond
[GROUP BY group] [HAVING group_cond]
[ORDER BY sort_key]
INTO|APPENDING target
[UP TO n ROWS]
[BYPASSING BUFFER]
[CONNECTION con|(con_syntax).
Pour rappel, les instructions entre crochets sont optionnelles.
Tout d’abord le SELECT est l’instruction pour la lecture d’une table. Depuis la nouvelle version de SAP (pour rappel, de la version Ehp6 à Ehp7), prête pour l’interaction avec les bases de données HANA, beaucoup de fonctions sont apparues et il serait intéressant de s’y attarder.
Pour résumer, un SELECT a quatre paramètres et cette instruction pourrait se résumer à ceci :
SELECT col
FROM table
INTO dest
WHERE cond.
Sélection des colonnes col de la table table, à stocker dans dest, répondant aux conditions cond.
Ainsi cette section se divisera en quatre parties : le SELECT des colonnes avec ses options, le FROM, le INTO et le WHERE, puis une partie sur les options de l’instruction même.
1. SELECT
a. SINGLE [FOR UPDATE]
Cette option permet de sélectionner une seule ligne de la table déclarée dans le FROM. Bien entendu, le stockage défini dans le INTO ne peut être une table interne et sera nécessairement une structure ou une liste de variables.
Exemple
DATA s_driver_car TYPE zdriver_car.
SELECT SINGLE *
FROM zdriver_car
INTO @s_driver_car.
L’option ’*’ signifie ’tous les champs’ et donc cette requête indique : sélectionner tous les champs du premier enregistrement de la table ZDRIVER_CAR et stocker dans la structure S_DRIVER_CAR.
Le symbole ’@’ défini comme escape character en anglais (se traduisant par caractère d’évasion) indique simplement que la variable, table interne ou structure fait partie des objets du programme et est donc externe à la base de données.
Résultat - structure S_DRIVER_CAR
MANDT |
900 |
ID_DRIVER |
C0001 |
SURNAME |
DEBBACHE |
NAME |
AMINH |
DATE_BIRTH |
19781216 |
CITY |
TOULOUSE |
COUNTRY |
FR |
CAR_BRAND |
PEUGEOT... |
INSERT
Cette requête permet d’ajouter une ou plusieurs lignes à la table de la base de données soit via une structure, soit via une table interne, et de mettre à jour deux variables système :
-
SY-SUBRC pour indiquer l’état de l’opération :
-
0 - la ou les lignes ont été correctement insérées.
-
4 - une ou plusieurs erreurs se sont produites pendant le traitement.
-
SY-DBCNT retourne le nombre de lignes insérées
Via une structure
INSERT INTO dbtab VALUES struct.
Le système va tout d’abord vérifier que la clé primaire de l’enregistrement contenu dans la structure struct n’existe pas dans la table de base de données dbtab, pour ainsi l’insérer et retourner un code retour à 0. Si la clé primaire existe, l’enregistrement ne sera pas ajouté et le code retour sera égal à 4.
Exemple
Insérer un nouveau passager dans la table ZPASSENGER.
DATA: s_passager TYPE zpassenger.
s_passager-id_passenger = 'P0005'.
s_passager-surname = 'THIERRY'.
s_passager-name = 'ROMAIN'.
s_passager-date_birth = '19930324'.
s_passager-city = 'MONTPELLIER'. ...
UPDATE
Ce type de requête permet de mettre à jour une ou plusieurs lignes de la table de la base de données de trois manières différentes, et mettra à jour deux variables système :
-
SY-SUBRC pour indiquer l’état de l’opération :
-
0 - la ou les lignes ont été correctement mises à jour.
-
4 - une ou plusieurs erreurs se sont produites pendant le traitement.
-
SY-DBCNT retourne le nombre de lignes mises à jour.
SET
UPDATE dbtab SET col1 = exp1, SET col2 = exp2,... [WHERE cond]...
Cette fonction signifie mettre à jour la table de la base de données dbtab, en appliquant la valeur définie par exp1 à la colonne col1, exp2 à col2...(SET) pour la condition cond définie (WHERE).
Les valeurs des champs sont modifiées directement dans la requête et même si la clause WHERE est optionnelle, elle est cependant bien recommandée au risque de modifier tous les enregistrements de la table.
Exemple
Pour le conducteur dont l’identifiant est ’C0003’, rajouter 5 euros pour tous les péages et 10 pour l’essence.
CONSTANTS: c_id_driver TYPE zdriver_id VALUE 'C0003'.
UPDATE ztravel
SET toll = toll + 5,
gasol = gasol + 10
WHERE id_driver = @c_id_driver.
IF sy-subrc = 0.
WRITE 'Mise à jour réussie'.
ELSE.
WRITE 'Echec de la mise à jour'.
ENDIF.
La constante C_ID_DRIVER est créée avec le type ZDRIVER_ID et contient la valeur ’C0003’. Le programme procédera ensuite à la mise à jour de la table ZTRAVEL en ajoutant la valeur de 5 au champ TOLL, et 10 à celui de GASOL, pour tous les enregistrements dont le champ ID_DRIVER est égal à la constante C_ID_DRIVER. Si le code retour de la variable système est égal à 0, le programme affichera le texte ’Mise à jour réussie’, dans le cas contraire, il affichera...
MODIFY
Cette requête permet de modifier une ou plusieurs lignes de la table de base de données soit via une structure, soit via une table interne, et de mettre à jour deux variables système :
-
SY-SUBRC indique l’état de l’opération
-
SY-DBCNT retourne le nombre de lignes modifiées
MODIFY dbtab FROM struct.
MODIFY dbtab FROM TABLE itab.
Elle se comporte de la même manière qu’un INSERT et un UPDATE : le système va vérifier si la ou les clé(s) primaire(s) définie(s) dans la structure struct ou la table interne itab existe(nt) dans la table de la base de données dbtab. Si celle-ci existe, alors la ligne sera modifiée (UPDATE), sinon elle sera créée (INSERT). Dans la majorité des cas, la variable système SY-SUBRC sera égale à 0.
DELETE
Cette requête permet de supprimer une ou plusieurs lignes de la table de base de données soit via une structure, soit via une table interne, et de mettre à jour deux variables système :
-
SY-SUBRC indique l’état de l’opération :
-
0 - la ou les lignes ont été correctement mises à jour.
-
4 - une ou plusieurs erreurs se sont produites pendant le traitement.
-
SY-DBCNT retourne le nombre de lignes supprimées
DELETE dbtab FROM struct.
DELETE dbtab FROM TABLE itab.
La logique est la même que pour un INSERT ou un UPDATE : le système va vérifier si la (ou les) clé(s) primaire(s) définie(s) dans la structure struct ou la table interne itab existe(nt) dans la table de la base de données dbtab. Si celle-ci existe, alors la ligne sera supprimée, sinon elle sera mise de côté et retournera la variable de retour SY-SUBRC à 4.
Il existe également une autre manière de procéder à un DELETE avec la clause WHERE.
DELETE FROM dbtab WHERE. . .
Exemple
Supprimer le passager avec l’identifiant ’P0005’ dans la table ZPASSENGER.
CONSTANTS: c_user_id TYPE zpassenger_id VALUE 'P0005'.
DELETE FROM zpassenger WHERE id_passenger = @c_user_id.
IF sy-subrc = 0.
WRITE 'L''enregistrement a été supprimé avec succès'. ...
Index
Comme vu dans le chapitre Dictionnaire de données (DDIC), un index est une clé secondaire à une table de base de données, permettant d’améliorer considérablement les performances d’une sélection. Après avoir défini cette notion, il serait intéressant de voir comment l’utiliser dans une requête SQL.
Exemple
Sélection des enregistrements de la table ZTRAVEL mais avec un filtre sur les champs CITY_FROM et COUNTRY_FROM.
CONSTANTS: c_city_from TYPE ztravel-city_from VALUE 'TOULOUSE',
c_ctry_from TYPE ztravel-country_from VALUE 'FR'.
SELECT city_from,
country_from,
city_to,
country_to,
date_travel,
hour_travel
FROM ztravel
INTO TABLE @DATA(t_travel)
WHERE city_from = @c_city_from
AND country_from = @c_ctry_from.
Comme la sélection s’effectue sur des champs non clés de la table, il est possible, avec l’augmentation du nombre...
Exercice
Créer un programme Z via la transaction SE38.
En reprenant les données définies en début de chapitre, insérer les enregistrements suivants dans la table ZTRAVEL et donner un statut de succès ou d’échec de cette opération :
CHAMP |
VALEUR_1 |
VALEUR_2 |
DATE_TRAVEL |
13.02.2018 |
13.02.2018 |
HOUR_TRAVEL |
08:00 |
15:30 |
ID_DRIVER |
C0002 |
C0003 |
ID_PASSENGER1 |
P0003 |
P0001 |
ID_PASSENGER2 |
P0002 |
|
ID_PASSENGER3 |
P0004 |
|
CITY_FROM |
LERIDA |
PERPIGNAN |
COUNTRY_FROM |
ES |
FR |
CITY_TO |
BARCELONE |
MONTPELLIER |
COUNTRY_TO |
ES |
FR |
KMS |
190 |
160 |
KMS_UNIT |
KM |
KM |
DURATION |
120 |
110 |
TOLL |
11 |
18 |
GASOL |
68 |
98 |
UNIT |
EUR |
EUR |
Une première sélection ira importer les enregistrements de la table ZTRAVEL et afficher pour chaque date de voyage les champs suivants :
-
Le nombre de voyages effectués
-
Le total des durées de voyage
-
Le total des distances parcourues
-
Le total des coûts de péage
-
Le total des coûts en carburant
-
Le total de tous les coûts journaliers
La table interne devra être déclarée dans un DATA après avoir défini son type TYPES.
Le résultat sera affiché à l’écran avec un LOOP et l’instruction WRITE (mise en page libre).
Une deuxième sélection importera une nouvelle fois les enregistrements de la table ZTRAVEL mais affichera les champs suivants :
-
Date de voyage
-
Heure de voyage
-
Nom et prénom...