0% ont trouvé ce document utile (0 vote)
45 vues31 pages

S8 - S9 - Cours - SQL Server 3IIR

Transféré par

bettalmehdi28
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
45 vues31 pages

S8 - S9 - Cours - SQL Server 3IIR

Transféré par

bettalmehdi28
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Module:

SYSTEMES D’INFORMATION 2 ET BASE DE DONNEES 2

Matière:
SQL Server

Chapitre VI: Les curseurs

**********************

Professeure Nadia OUKRICH


[Link]@[Link]

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 1


Plan du cours

1. Présentation de l’environnement de SQLSERVER


2. Introduction au langage Transact SQL (T_SQL)
3. Structure d’un programme T_SQL
4. Les variables et leurs types
5. Les structures alternatives (de contrôle)
6. Les procédures stockées & Les fonctions stockées
7. La gestion des exceptions
8. Les curseurs
9. Les déclencheurs
13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 2
Définition du curseur

Un curseur en T-SQL est un mécanisme qui permet de parcourir ligne par ligne

le résultat d'une requête, afin de traiter chaque enregistrement individuellement.

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 3


Avantages et inconvénients

Utilisation recommandée uniquement si :


✓ Il est nécessaire de traiter ligne par ligne,
✓ L’opération ne peut pas être facilement faite avec une requête SQL
classique,
✓ Tu dois appliquer des traitements complexes, conditionnels ou appeler des
procédures stockées pour chaque ligne.

Inconvénients
▪ Moins performant que les requêtes ensemblistes,
▪ Consomme plus de ressources (mémoire, CPU),
▪ À éviter sur de grandes tables.

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 4


Syntaxe générale
-- Déclaration du curseur
DECLARE nom_curseur CURSOR FOR
SELECT colonne1, colonne2 FROM ma_table;

-- Ouverture du curseur
OPEN nom_curseur;

-- Variables pour stocker les lignes


DECLARE @var1 INT, @var2 NVARCHAR(100);

-- Lecture initiale
FETCH NEXT FROM nom_curseur INTO @var1, @var2;

-- Boucle
WHILE @@FETCH_STATUS = 0
BEGIN
-- Traitement ligne par ligne
PRINT 'Valeur : ' + CAST(@var1 AS NVARCHAR) + ', ' + @var2;

-- Lire la ligne suivante


FETCH NEXT FROM nom_curseur INTO @var1, @var2;
END;

-- Fermeture et libération des ressources


CLOSE nom_curseur;
13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 5
DEALLOCATE nom_curseur;
Syntaxe générale
1. Déclaration du curseur

DECLARE nom_curseur CURSOR FOR


SELECT colonne1, colonne2 FROM ma_table;

• Cette commande crée un curseur nommé nom_curseur basé sur le résultat de la


requête SELECT.
• Dans cet exemple, le curseur va parcourir chaque ligne du résultat de la requête SELECT
colonne1, colonne2 FROM ma_table.

2. Ouverture du curseur

OPEN nom_curseur;

• Cette commande exécute la requête SELECT liée au curseur et prépare le curseur à


lire les données ligne par ligne.

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 6


Syntaxe générale

3. Déclaration des variables

DECLARE @var1 INT, @var2 NVARCHAR(100);

• Ces variables vont recevoir les valeurs des colonnes pour chaque ligne parcourue par le
curseur :
➢ @var1 stocke colonne1 (de type entier)
➢ @var2 stocke colonne2 (chaîne de caractères).

4. Lecture initiale

FETCH NEXT FROM nom_curseur INTO @var1, @var2;

• Cette commande lit la première ligne du curseur et stocke les valeurs dans @var1 et
@var2.

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 7


Syntaxe générale

5. Boucle de traitement

WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'Valeur : ' + CAST(@var1 AS NVARCHAR) +
', ' + @var2;

FETCH NEXT FROM nom_curseur INTO @var1, @var2;


END;

@@FETCH_STATUS retourne :
0 si la lecture a réussi (il y a une ligne),
-1 si c’est la fin du curseur,
-2 en cas d’erreur.

• Tant qu'il reste des lignes à lire (@@FETCH_STATUS = 0), la boucle continue :Il
affiche les valeurs (PRINT),Ensuite il lit la ligne suivante (FETCH NEXT...).

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 8


Syntaxe générale

6. Fermeture et libération du curseur

CLOSE nom_curseur;
DEALLOCATE nom_curseur;

CLOSE : Ferme le curseur (il n’est plus utilisable tant qu’il n’est pas rouvert).
DEALLOCATE : Supprime le curseur de la mémoire (libère les ressources).

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 9


Exemple 1: Curseur Simple

Afficher tous les noms de clients ainsi que les dates de leurs commandes:

DECLARE curseur_clients CURSOR FOR


SELECT [Link], [Link], CMD.Date_commande
FROM Client C
JOIN Commande CMD ON C.ID_Client = CMD.ID_Client;

DECLARE @Nom NVARCHAR(100), @Prenom NVARCHAR(100), @DateCommande DATE;

OPEN curseur_clients;

FETCH NEXT FROM curseur_clients INTO @Nom, @Prenom, @DateCommande;


WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'Client : ' + @Nom + ' ' + @Prenom + ' - a Commandé le : ' +
CONVERT(NVARCHAR, @DateCommande, 103);
FETCH NEXT FROM curseur_clients INTO @Nom, @Prenom, @DateCommande;
END;

CLOSE curseur_clients;
DEALLOCATE curseur_clients;
13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 10
Résultat de l’exemple1: Curseur Simple

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 11


Exemple 2: Curseur Simple
Mettre à jour les commissions des employés en fonction de leur ancienneté
DECLARE curseur_employes CURSOR FOR
SELECT ID_Employe, Date_entree, Commission
FROM Employe;

DECLARE @ID INT, @DateEntree DATE, @Commission FLOAT;


DECLARE @Anciennete INT;

OPEN curseur_employes;

FETCH NEXT FROM curseur_employes INTO @ID, @DateEntree, @Commission;


WHILE @@FETCH_STATUS = 0
BEGIN
SET @Anciennete = DATEDIFF(YEAR, @DateEntree, GETDATE());
IF @Anciennete > 2
BEGIN
UPDATE Employe
SET Commission = Commission + 1000
WHERE ID_Employe = @ID;
PRINT 'Mise à jour : Employé ID ' + CAST(@ID AS NVARCHAR) +
'sa commission est: ' + CAST(@Commission AS NVARCHAR) + ' dh';
END
FETCH NEXT FROM curseur_employes INTO @ID, @DateEntree, @Commission;
END;

CLOSE curseur_employes;
DEALLOCATE curseur_employes;
13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 12
Résultat Exemple 2: Curseur Simple
Mettre à jour les commissions des employés en fonction de leur ancienneté

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 13


Les options avancées du curseur
❑ Permet d’optimiser les performances et le comportement du curseur selon les
besoins.

DECLARE Nom_Curseur CURSOR


[ LOCAL | GLOBAL ]
[ FORWARD_ONLY | SCROLL ]
[ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]
[ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]
FOR
requête_SQL;

1- Portée du curseur (LOCAL / GLOBAL)


Option Explication Exemple
Le curseur est visible uniquement
Par défaut dans les procédures
LOCAL dans le bloc (BEGIN...END), procédure
stockées.
stockée, ou trigger où il est défini.
Le curseur est visible dans toute la Si tu veux accéder au curseur
GLOBAL
session SQL. après la fin du bloc de code.
13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 14
Les options avancées du curseur

DECLARE Nom_Curseur CURSOR


[ LOCAL | GLOBAL ]
[ FORWARD_ONLY | SCROLL ]
[ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]
[ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]
FOR
requête_SQL;

2- Navigation dans le curseur (FORWARD_ONLY / SCROLL)

Option Explication Exemple


Lecture uniquement vers l'avant, Très rapide et faible en
FORWARD_ONLY
une ligne à la fois avec FETCH NEXT. ressources.
Permet de naviguer dans toutes les Plus de flexibilité, mais
SCROLL directions : FIRST, LAST, PRIOR, plus coûteux en en
ABSOLUTE, etc. ressources.

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 15


Les options avancées du curseur
DECLARE Nom_Curseur CURSOR
[ LOCAL | GLOBAL ]
[ FORWARD_ONLY | SCROLL ]
[ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]
[ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]
FOR
requête_SQL;

3- Type de curseur (comportement)


Option Explication Avantages / Inconvénients
Fait une copie complète des résultats dans le
+ Rapide pour lecture – Pas de
STATIC curseur. Ne reflète aucun changement dans la
mise à jour visible
table d'origine.
La structure (ensemble de lignes) est fixée à + Voit UPDATE – Ne voit pas
KEYSET
l'ouverture, mais les mises à jour sont visibles. INSERT/DELETE
Le curseur voit tous les changements sur la
DYNAMIC table (ajouts, suppressions, modifs) en temps + Réactif – Plus lent, gourmand
réel.
Combine FORWARD_ONLY + READ_ONLY. + Très performant – Pas de mise
FAST_FORWARD
Lecture rapide sans possibilité de modification. à jour
13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 16
Les options avancées du curseur
DECLARE Nom_Curseur CURSOR
[ LOCAL | GLOBAL ]
[ FORWARD_ONLY | SCROLL ]
[ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]
[ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]
FOR
requête_SQL;

4- Concurrence / Verrouillage (READ_ONLY, SCROLL_LOCKS, OPTIMISTIC)

Option Explication Cas d’usage


Interdit toute tentative de Lecture uniquement.
READ_ONLY
modification via le curseur. Parfait pour reporting.
Verrouille chaque ligne lue, évite Lecture cohérente dans
SCROLL_LOCKS qu’elle soit modifiée par un autre les environnements
utilisateur. multi-utilisateurs.
Pas de verrouillage. Mais vérifie
Bon compromis entre
OPTIMISTIC que la ligne n’a pas changé avant
performance et intégrité.
l’UPDATE.
13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 17
Exemple 1: Avec options avancées
Afficher tous les noms de clients ainsi que les dates de leurs commandes:
DECLARE curseur_clients CURSOR LOCAL FORWARD_ONLY FAST_FORWARD READ_ONLY
FOR
SELECT [Link], [Link], CMD.Date_commande
FROM Client C
JOIN Commande CMD ON C.ID_Client = CMD.ID_Client
WHERE CMD.Date_commande >= '2023-01-01'
ORDER BY CMD.Date_commande DESC;
DECLARE @Nom NVARCHAR(100),
@Prenom NVARCHAR(100),
@DateCommande DATE;
OPEN curseur_clients;
FETCH NEXT FROM curseur_clients INTO @Nom, @Prenom, @DateCommande;
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'Client : ' + @Nom + ' ' + @Prenom + ' - a commandé le : ' +
CONVERT(NVARCHAR, @DateCommande, 103);
FETCH NEXT FROM curseur_clients INTO @Nom, @Prenom, @DateCommande;
END;
CLOSE curseur_clients;
DEALLOCATE curseur_clients;

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 18


Exemple 1: Avec options avancées
L’intéret des options pour l’exemple :

DECLARE curseur_clients CURSOR LOCAL FORWARD_ONLY FAST_FORWARD READ_ONLY


FOR
….

Dans cet exemple, nous effectuons un parcours simple, en lecture seule, ligne par ligne,

sans retour en arrière, sans saut de ligne et sans modification des données.

Cela ne nécessite ni édition, ni navigation complexe, ce qui permet :

➢ de gagner en vitesse d’exécution ;

➢ de réduire l’utilisation de la mémoire et de tempdb ;

➢ de simplifier la gestion des ressources (moins de verrous, de journaux, etc.).

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 19


TP 7 – Partie 1

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 20


Exemple 2: avec Curseur statique
Mettre à jour les commissions des employés en fonction de leur ancienneté
DECLARE curseur_employes CURSOR STATIC FOR
SELECT ID_Employe, Date_entree, Commission
FROM Employe;

DECLARE @ID INT, @DateEntree DATE, @Commission FLOAT;


DECLARE @Anciennete INT;

-- Insertion OPEN curseur_employes;

dans la insert into Employe


table après VALUES (6, 'El Amrani', 'Khalid', '20210310', 'Manager', 'Marketing', 10000.00, 1200.00)

ouverture FETCH NEXT FROM curseur_employes INTO @ID, @DateEntree, @Commission;


WHILE @@FETCH_STATUS = 0
du curseur BEGIN
SET @Anciennete = DATEDIFF(YEAR, @DateEntree, GETDATE());
IF @Anciennete > 2
BEGIN
UPDATE Employe
SET Commission = Commission + 1000
WHERE ID_Employe = @ID;
PRINT 'Mise à jour : Employé ID ' + CAST(@ID AS NVARCHAR) +
'sa commission est: ' + CAST(@Commission AS NVARCHAR) + ' dh';
END
FETCH NEXT FROM curseur_employes INTO @ID, @DateEntree, @Commission;
END;
CLOSE curseur_employes;
DEALLOCATE curseur_employes;

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 21


Exemple 2: sans Curseur statique
Mettre à jour les commissions des employés en fonction de leur ancienneté
DECLARE curseur_employes CURSOR FOR
SELECT ID_Employe, Date_entree, Commission
FROM Employe;

DECLARE @ID INT, @DateEntree DATE, @Commission FLOAT;


DECLARE @Anciennete INT;

-- Insertion OPEN curseur_employes;

dans la insert into Employe


table après VALUES (7, ‘Rachid', ‘Salma', ‘20200101', ‘RH', ‘RH’, 20000.00, 2000.00)

ouverture FETCH NEXT FROM curseur_employes INTO @ID, @DateEntree, @Commission;


WHILE @@FETCH_STATUS = 0
du curseur BEGIN
SET @Anciennete = DATEDIFF(YEAR, @DateEntree, GETDATE());
IF @Anciennete > 2
BEGIN
UPDATE Employe
SET Commission = Commission + 1000
WHERE ID_Employe = @ID;
PRINT 'Mise à jour : Employé ID ' + CAST(@ID AS NVARCHAR) +
'sa commission est: ' + CAST(@Commission AS NVARCHAR) + ' dh';
END
FETCH NEXT FROM curseur_employes INTO @ID, @DateEntree, @Commission;
END;
CLOSE curseur_employes;
DEALLOCATE curseur_employes;

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 22


Exemple 2 avec Curseur statique: explication

Quand tu déclares un curseur avec le mot-clé STATIC :

• SQL Server prend un "instantané" (snapshot) des résultats de la requête

au moment où le curseur est ouvert (OPEN).

• Il stocke cette copie dans une table temporaire (dans tempdb), et ne

regarde plus la table réelle pendant le parcours du curseur.

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 23


CURSEUR SCROLL
Commande FETCH Description
FETCH NEXT FROM Lit la ligne suivante
FETCH PRIOR FROM Lit la ligne précédente
FETCH FIRST FROM Lit la première ligne
FETCH LAST FROM Lit la dernière ligne
FETCH ABSOLUTE n FROM Lit la nième ligne absolue (n =1: première, -1 : dernière)
FETCH RELATIVE n FROM Lit la ligne relative à la position actuelle (+1 = next, -1 = prior)

n négatif 1
n négatif

-1
ABSOLUTE n
RELATIVE n
+1
n positif
-1
n positif

SI n EST EN DEHORS DU CURSEUR: PAS DE DEPLACEMENT


14/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 24
Exemple 1: Avec Curseur SCROLL
Afficher tous les noms de clients ainsi que les dates de leurs commandes:
DECLARE curseur_clients SCROLL CURSOR FOR
SELECT [Link], [Link], CMD.Date_commande
FROM Client C
JOIN Commande CMD ON C.ID_Client = CMD.ID_Client;
DECLARE @Nom NVARCHAR(100), @Prenom NVARCHAR(100), @DateCommande DATE;
OPEN curseur_clients;
FETCH FIRST FROM curseur_clients INTO @Nom, @Prenom, @DateCommande;
PRINT 'Premier client : ' + @Nom + ' ' + @Prenom + ' - a Commandé le : ' +
CONVERT(NVARCHAR, @DateCommande, 103);
FETCH NEXT FROM curseur_clients INTO @Nom, @Prenom, @DateCommande;
PRINT 'Client suivant : ' + @Nom + ' ' + @Prenom + ' - a Commandé le : ' +
CONVERT(NVARCHAR, @DateCommande, 103);
FETCH PRIOR FROM curseur_clients INTO @Nom, @Prenom, @DateCommande;
PRINT 'Client précédent : ' + @Nom + ' ' + @Prenom + ' - a Commandé le : ' +
CONVERT(NVARCHAR, @DateCommande, 103);
FETCH LAST FROM curseur_clients INTO @Nom, @Prenom, @DateCommande;
PRINT 'Dernier client : ' + @Nom + ' ' + @Prenom + ' - a Commandé le : ' +
CONVERT(NVARCHAR, @DateCommande, 103);
FETCH ABSOLUTE 3 FROM curseur_clients INTO @Nom, @Prenom, @DateCommande;
PRINT 'Client en position 3 : ' + @Nom + ' ' + @Prenom + ' - a Commandé le : ' +
CONVERT(NVARCHAR, @DateCommande, 103);
FETCH RELATIVE -2 FROM curseur_clients INTO @Nom, @Prenom, @DateCommande;
PRINT 'Client 2 positions avant : ' + @Nom + ' ' + @Prenom + ' - a Commandé le : ' +
CONVERT(NVARCHAR, @DateCommande, 103);
CLOSE curseur_clients;
DEALLOCATE curseur_clients;
Exemple 1: Avec Curseur SCROLL

Afficher tous les noms de clients ainsi que les dates de leurs commandes:
Extrait de La table Client

…..
…..

Résultat de l’Exemple 1: Avec Curseur SCROLL


FETCH FIRST
FETCH NEXT
FETCH PRIOR
FETCH LAST
FETCH ABSOLUTE 3
FETCH RELATIVE -2
14/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 26
Curseur KEYSET

Fonction Description
Permet de naviguer dans toutes les directions (FIRST, LAST, NEXT,
Lecture
PRIOR, ABSOLUTE, RELATIVE).
Les modifications (UPDATE) effectuées sur les lignes de la table sont
Mise à jour
visibles via le curseur.
Les lignes supprimées sont visibles comme “non disponibles” et ne
Suppression
peuvent plus être lues par le curseur (@@FETCH_STATUS = -2)
Les nouvelles lignes insérées après l’ouverture du curseur ne sont
Insertion
pas visibles.

13/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 27


Exemple 3: Curseur KEYSET
Utilisation du curseur KEYSET pour l'affichage des clients:

DECLARE @ID INT, @NOM VARCHAR(50), @PRENOM VARCHAR(50), @ADRESSE VARCHAR(50),


@VILLE VARCHAR(50), @PAYS VARCHAR(50);

DECLARE usdCURSOR_KEYSET CURSOR


KEYSET FOR SELECT ID_Client, NOM, PRENOM, ADRESSE, VILLE, PAYS FROM CLIENT;

OPEN usdCURSOR_KEYSET;
IF @@CURSOR_ROWS> 0
BEGIN FETCH NEXT FROM usdCURSOR_KEYSET INTO @ID, @NOM, @PRENOM, @ADRESSE,
@VILLE, @PAYS
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'ID= ' + CONVERT (VARCHAR (10), @ID) + ', Nom complet= ' +
@NOM+''+@PRENOM+ ', ADRESSE= ' + @ADRESSE + ', VILLE= ' + @VILLE + ',
PAYS= ' + @PAYS;

FETCH NEXT FROM usdCURSOR_KEYSET


INTO @ID, @NOM, @PRENOM, @ADRESSE, @VILLE, @PAYS
END
END
CLOSE usdCURSOR_KEYSET
DEALLOCATE usdCURSOR_KEYSET
14/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 28
Exemple 3: Curseur KEYSET
Exemple d'utilisation du curseur KEYSET avec test de modification et insertion:
DECLARE @ID INT, @DateEntree DATE, @Commission DECIMAL(10,2);
DECLARE employeCURSOR_KEYSET CURSOR
KEYSET FOR
SELECT ID_Employe, Date_entree, Commission
FROM Employe;
OPEN employeCURSOR_KEYSET;

Modification -- Modification (visible par le curseur KEYSET)


UPDATE Employe
SET Commission = ISNULL(Commission, 0) + 500
WHERE ID_Employe = 1;

Insertion -- Insertion (non visible car le curseur est déjà ouvert)


INSERT INTO Employe (ID_Employe, Nom, Prenom, Date_entree, Titre, Servicee, Salaire, Commission)
VALUES (9, 'Sabri', 'Noura', '2021-01-15', 'Assistante', 'RH', 7000.00, 800.00);

IF @@CURSOR_ROWS > 0
BEGIN
FETCH NEXT FROM employeCURSOR_KEYSET INTO @ID, @DateEntree, @Commission;

WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'ID = ' + CAST(@ID AS VARCHAR) +
', Date d''entrée = ' + CONVERT(VARCHAR, @DateEntree) +
', Commission = ' + CAST(@Commission AS VARCHAR);

FETCH NEXT FROM employeCURSOR_KEYSET INTO @ID, @DateEntree, @Commission;


END
END

CLOSE employeCURSOR_KEYSET;
DEALLOCATE employeCURSOR_KEYSET;
Exemple 3: Curseur KEYSET
Résultat du test de modification et insertion : Exemple d'utilisation du curseur KEYSET :

Le curseur KEYSET :
•ne voit pas les lignes insérées après son ouverture : 9, 'Sabri', 'Noura'…
• voit les modifications de lignes existantes: La commission ligne 1

14/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 30


TP 7 – Partie 2

14/05/2025 Pr. Nadia Oukrich. SQL Server 3IIR 31

Vous aimerez peut-être aussi