51
Vues

Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

Embed Size (px)

Citation preview

Page 1: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

Vues

Page 2: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

2/51

Vues

Table deriveé des tables existants (table de base) Accès adapte a besoin d'application (couche

externe) Stockage des requêtes Protection des donneés

Utilization Recherche comme table de base MAJ largement limiteé

Page 3: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

3/51

CREATE VIEWCREATE VIEW capitale_olympique (année, pays,

capitale)

AS SELECT année, JO.pays, capitale

FROM JO, Pays

WHERE JO.pays = Pays.nom

Page 4: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

4/51

Utilisation des Vues

SELECT DISTINCT capitale FROM capitale_olympique ;

UPDATE capitale_olympiqueSET capitale = 'Berlin' WHERE pays = 'RDA';

Page 5: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

5/51

MAJ des vues

Les modifications sont possibles si la requête ne contient pas de Jointure Opérateur d’agrégation Attribut calculé dans le SELECT UNION, INTERSECT, DIFFERENCE, DISTINCT,

GROUP BY, ORDER BY

Page 6: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

6/51

Exemple

CREATE VIEW pays_europenne AS SELECT * FROM PaysWHERE continent = 'Europe' ;

UPDATE pays_europenne SET capitale = 'Berlin' WHERE nom = 'RDA';

Le changement est propagé vers la table de base!

Page 7: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

7/51

Exemple – MAJ impossible

CREATE VIEW comparaison AS SELECT P1.nom, P1.population, P2.nom, P2.populationFROM Pays P1, Pays P2WHERE P1.population > P2.population ;

DELETE ?

Il n'existe aucune possibilité d‘éliminer seulementce tuple et de maintenir la consistance avec les tables de base

Page 8: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

8/51

Vue Materialisée

Normalement, seulement la définition de la vue est stockée

Vue materialisée Crée une novelle table contenant les résultats de la

requête utilisée dans la définition de la vue Si les tables de base changent: MAJ de la vue

matérialisée

CREATE MATERIALIZED VIEW capitale_olympique(année, pays, capitale)

REFRESH FAST ON COMMITAS SELECT année, JO.pays, capitale

FROM JO, PaysWHERE JO.pays = Pays.nom ;

Page 9: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

9/51

Commandes sur les vues

CREATE [OR REPLACE] VIEW nom_vue [ ( nv_nom_col)*] AS requête [WITH READ ONLY] [WITH CHECK OPTION] ; OR REPLACE: remplace une vue existante WITH READ ONLY: interdit les MAJ WITH CHECK OPTION: insertions et modifications seulement

si le tuple résultant est sélectionné par la vue

DROP VIEW nom_vue;

RENAME nom_vue TO nv_nom;

ALTER VIEW nom_vue COMPILE; Recalcule une vue

Page 10: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

Maintenir les contraintes d'intégrité

Page 11: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

11/51

Contraintes d'intégrité

Plusieurs possibilités pour les maintenir Définition des tables Assertions Triggers Vues

Page 12: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

12/51

Rappel Contrainte sur une colonne (contrainte-col)

[NOT] NULL UNIQUE PRIMARY KEY

Contraintes sur une table (contrainte-table) UNIQUE (nom-col)* PRIMARY KEY (nom-col)* FOREIGN KEY (nom-col)*

REFERENCES nom_table [(nom-col)*]

Page 13: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

13/51

Identifiant externe

Maintenir l’intégrité référentielle Lors de suppressions ou modifications d'un tuple

dont l'identifiant est référencé par un identifiant externe

Exemple de problème Pays(nom, capitale, population, surface)

JO(lieu, pays, année) Suppression d'un tuple de Pays:

DELETE FROM Pays WHERE nom='Grece';

Page 14: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

14/51

Maintenir integrite referentielle

Possibilités Interdire l'opération Mettre les valeurs de l'identifiant externe à NULL

ou à une valeur défaut En cas du suppression: éliminer aussi le tuple

avec l'identifiant externe En cas du modification: modifier également la

valeur de l'identifiant externe

Page 15: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

15/51

Exemple

CREATE TABLE JO

( année DECIMAL(4,0), lieu VARCHAR(15),

pays VARCHAR(20), PRIMARY KEY (année),

FOREIGN KEY (pays) REFERENCES Pays (nom)

ON DELETE SET NULL

ON UPDATE CASCADE

);

Page 16: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

16/51

Contraintes complexes

Maintenir les conditions logique sur les tuples

Exemple Pays(nom, capitale, population, surface)

JO(lieu, pays, année) JO.année 1896 3 jeux olympiques au maximum dans le même

pays

Page 17: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

17/51

Assertion simple

Spécification de la condition pendant la définition de la table La condition est contrôlée avec chaque modification ou insertion

ExempleCREATE TABLE JO

( année DECIMAL(4,0), lieu VARCHAR(15),

pays VARCHAR(20), PRIMARY KEY (année),

FOREIGN KEY (pays) REFERENCES Pays (nom)

ON DELETE SET NULL

ON UPDATE CASCADE

CHECK(année 1896) );

Page 18: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

18/51

Assertion avec requête

CREATE TABLE JO

( année DECIMAL(4,0), lieu VARCHAR(15),

pays VARCHAR(20), PRIMARY KEY (année),

FOREIGN KEY (pays) REFERENCES Pays (nom)

ON DELETE SET NULL

ON UPDATE CASCADE,

CHECK(année 1896)

CHECK(3 ALL (SELECT COUNT(*) FROM JO

GROUP BY pays) );

Page 19: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

19/51

Assertion globale

Condition sur plusiers tables Definition independant d'une table

Exemple: deux jeux olympiques consécutifs ne se déroulent pas sur le même continent

CREATE ASSERTION JO_consecutive CHECKNOT EXISTS (

SELECT * FROM JO JO1, JO JO2, Pays P1, Pays P2WHERE JO1.pays=P1.nom AND

JO2.pays=P2.nom AND JO1.année=JO2.année+4 AND P1.continent=P2.continent);

Les assertions complexes sont très coûteuses !

Page 20: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

Triggers

Page 21: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

21/51

Trigger

Concept de base de données active

Exécuter une opération suite à un changement survenu dans la base de données Maintenir les contraintes d'intégrité Logging et auditing des changements Calculer des valeurs dérivées Maintenir des règles de business Maintenir des données répliquées et des vues

complexes materialisées etc.

Page 22: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

22/51

Evénement – Condition - Action

Un trigger est activé par un événement Insertion, suppression ou modification sur une table

Si le trigger est activé, une condition est évaluée Prédicat ou requête Une requête est vraie si le résultat n'est pas vide

Si la condition est vraie l'action est exécutée Insertion, suppression ou modification de la base de

données (ou programme externe)

Page 23: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

23/51

Exemple

CREATE TRIGGER MAJ_Pays AFTER UPDATE population ON PaysFOR EACH ROWWHEN surface > 0BEGIN

UPDATE Pays SET pop_avg =

population/surface;END;

événement

condition

action

Page 24: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

24/51

Exécution d'un trigger

Avant, après ou au lieu de l'événement AFTER | BEFORE | INSTEAD

Invocation de l'événement une fois par table ou pour tous les tuples affectés [FOR EACH ROW]

Association avec une transaction A la fin de la transaction en cours Transaction séparée

Page 25: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

25/51

Références aux valeurs modifiées CREATE TRIGGER MAJ_Log

AFTER UPDATE ON Pays FOR EACH ROW WHEN (new.surface <> old.surface) BEGIN

INSERT INTO Pays_log (nom, surface)

VALUES (:new.nom, 'surface_changée');

END;

Page 26: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

26/51

Syntaxe des triggers (SQL 1999)

CREATE TRIGGER [OR REPLACE] nom-du-trigger

BEFORE | AFTER | INSTEAD OF

INSERT | UPDATE | DELETE OF noms-d'attributs ON nom-table

[FOR EACH ROW]

WHEN (condition)

<bloc PL/SQL ou programme Java ou C >

Page 27: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

27/51

Attention

Les triggers sont très utiles et puissants

Mais: une utilisation prudente est nécessaire

Attention aux Invocations de cascade de triggers Utilisations excessives des ressources Difficultés pour prévoir les conséquences

Page 28: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

Embedded SQL

Page 29: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

29/51

Embedded SQL - but

Inclure des commandes SQL dans un programme (Java, C, Cobol, Ada, Fortran, Pascal, …) compléter SQL avec la puissance d’expressivité

d’un langage de programmation Interactions avec l’utilisateur, systèmes

périphériques, …

Exemples calculs, requêtes récursives, conversions, …

Page 30: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

30/51

Principe d’utilisation

Ecrire dans un LP quelconque un programme normal contenant en plus des ordres SQL Le langage qui “accueille” les ordres SGBD:

le langage hôte Les ordres accueillis: ordres inclus

Gérer les éventuels problèmes de communication entre le programme et le SGBD Transmission des données entre le langage hôte

et SQL

Page 31: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

31/51

Ordres inclus

Inclusion Syntaxe dépend du langage hôte En général: EXEC SQL <expression SQL> END-

EXEC En C: EXEC SQL <expression SQL> ; En Java: #SQL { <expression SQL> };

Exécution Précompilateur SQL détecte l’expressions SQL incluse remplacée par un appel à une fonction de la

bibliothèque de communication SGBD - langage hôte transmise au SGBD lors de l’exécution du programme

par cette fonction

Page 32: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

32/51

Transmission des données

Echange entre le SGBD et le programme réalisé au travers d’une zone de communication Zone de communication = ensemble de variables

Variables d’échange utilisateur (hôtes) données (insertions, interrogation) information du programme pour le SGBD

Variables spéciales SGBD informations du SGBD pour le programme

Page 33: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

33/51

Exemple – requête (langage hôte C)

…EXEC SQL BEGIN DECLARE SECTION;char titre[15]; /* titre obtenu par un utilisateur */real sal; /* salaire */

EXEC SQL END DECLARE SECTION;…/* Code (omis) pour obtenir un titre */EXEC SQL SELECT SalaireINTO :salFROM CompensationWHERE Titre = :titre;/* Code (omis) pour imprimer le resultat */…

Déclaration desvariables communes

Transmission de données

Page 34: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

34/51

Transmission d’un ensemble de données Le résultat d'une requête est une ensemble

de données Le langage hôte ne connaît pas le concept

d'ensemble Incompatibilité des langages ("Language

impendance mismatch")

Tampon (Cursor) zone mémoire nommée du programme à laquelle

une requête est associée taille dynamique réglée à l’exécution sert à contenir les n-uplets résultant de requête

Page 35: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

35/51

Tampon

Principe d’utilisation Déclaration du tampon (DECLARE) Remplissage du tampon en une seule fois par

exécution de la requête (OPEN) Récupération des n-uplets du tampon un par un

(FETCH) Libération du tampon (CLOSE)

.

.

.

Avant 1. tuple

Apres dernier tuple

1. tuple

dernier tuple

Page 36: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

36/51

Utilisation d'une tampon…

EXEC SQL BEGIN DECLARE SECTION;

<Déclaration des variables communes>

EXEC SQL END DECLARE SECTION;

EXEC SQL DECLARE <cursor-name> [options] CURSOR FOR <query> [options];

EXEC SQL OPEN <cursor-name> ;

while(condition) {

EXEC SQL FETCH FROM <cursor-name> INTO <shared-variable(s)> ;

if(tuple existe) traiter le tuple else break }

EXEC SQL CLOSE <cursor-name> ;

Page 37: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

37/51

Exemple

EXEC SQL DECLARE tamp1 CURSOR FOR

SELECT nom, prenom

FROM Etudiant

WHERE cle = :cle;

EXEC SQL OPEN tamp1

EXEC SQL FETCH FROM tamp1 INTO :nom, :prénom;

EXEC SQL CLOSE tamp1;

Page 38: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

38/51

Options - Declaration

EXEC SQL DECLARE <cursor-name>[INSENSITIVE][SCROLL] CURSOR FOR <query>[ORDER BY <attribute(s)>][FOR READ ONLY];

INSENSITIVE le tampon est insensible aux changements dans la relation

durant l’ouverture

SCROLL utilisation des options FETCH

ORDER BY trie l'ordre des tuples

FOR READ ONLY l'accès ne change pas le contenu des tuples

Page 39: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

39/51

Options - Accés

EXEC SQL FETCH [FROM] [ NEXT | PRIOR | FIRST | LAST | RELATIVE[+|-]n | ABSOLUTE[+|-]n ]<cursor-name>

[INTO <var1>,…, <varn>]

Page 40: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

40/51

Termination des SQL statements Unité de travail (= transaction) commence

avec le premier ordre SQL ou avec COMMIT/ROLLBACK

COMMIT Si on veut rendre le résultat de la transaction

permanent Syntaxe: EXEC SQL COMMIT;

ROLLBACK Si on veut rejeter le résultat de la transaction Syntax : EXEC SQL ROLLBACK;

Page 41: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

41/51

Gestion des exceptions : WHENEVER Gestion automatique des erreurs et warnings

teste tous les évènements qui suivent En général, un WHENEVER avant le premier ordre

SQL exécutable

Syntaxe

EXEC SQL WHENEVER <évènement> <action>;

Page 42: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

42/51

WHENEVER

Evénement SQLERROR, SQLWARNING NOT FOUND : si pas de n-uplet trouvé

Action CONTINUE, STOP (Rollback) GOTO branch (à éviter), DO f() DO BREAK et DO CONTINUE (à utiliser pour des

boucles)

Page 43: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

43/51

Exemple – mise a jour#include <stdio.h>

EXEC SQL INCLUDE SQLCA;main() {

EXEC SQL WHENEVER SQLERROR GOTO error:EXEC SQL CONNECT TO Company;

EXEC SQL BEGIN DECLARE SECTION;int pno1, pno2; /* two project numbers */int amount; /* amount to be transferred */

EXEC SQL END DECLARE SECTION;/* Code (omitted) to read the project numbers and amount */EXEC SQL UPDATE Project SET Budget = Budget + :amount WHERE Pno = :pno2;

EXEC SQL UPDATE ProjectSET Budget = Budget - :amountWHERE Pno = :pno1;

EXEC SQL COMMIT RELEASE;return(0);

error:printf(“update failed, sqlcode = %ld\n”, SQLCODE);EXEC SQL ROLLBACK RELEASE;return(-1);

}

Page 44: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

44/51

SQL dynamique

Si l'ordre SQL exact n'est pas connu lors du développement de l'application SQL n’autorise pas les variables tables ou colonnes

Possibilité d’avoir le texte de l’ordre SQL entier contenu dans une variable

Syntaxe:

EXEC SQL EXECUTE IMMEDIATE <Texte_ordre_SQL>;

Page 45: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

45/51

Exemple

EXEC SQL BEGIN DECLARE SECTION;

char req[] = “INSERT INTO EMP VALUES(‘E13’, ‘Jean Blanc’,...)”;

EXEC SQL END DECLARE SECTION;

EXEC SQL EXECUTE IMMEDIATE :req;

Limitations :req ne peut pas retourner de résultat :req ne peut pas contenir de paramètres Chaque fois que :req est exécutée, elle est

également compilée overhead important

Page 46: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

46/51

Exécution préparée

Forme généraleEXEC SQL PREPARE stmt FROM :string

Règle :string peut retourner des résultats d'une

requête :string peut contenir des paramètres stmt n’est pas une variable hôte, mais un

identificateur de l’ordre utilisé par le pré-processeur

Page 47: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

47/51

Exemple

EXEC SQL BEGIN DECLARE SECTION ;

char tup[] = “INSERT INTO EMP VALUES(‘E13’, ‘Jean Blanc’,...)”;

EXEC SQL END DECLARE SECTION;

EXEC SQL PREPARE S1 FROM :tup;

EXEC SQL EXECUTE S1;

...

EXEC SQL EXECUTE S1;

Page 48: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

48/51

Paramétrisation

Utiliser des caractères joker - ? – là où les chaînes de caractères peuvent apparaître "INSERT INTO Emp VALUES (?, ?, ?, ?)" pas à la place d’un nom de relation, de colonne, etc

Utiliser des variables hôtes dans la clause USING pour indiquer les valeurs des paramètres EXEC SQL EXECUTE S1 USING :eno, :ename, :title, :city

USING ne peut pas être employé avec EXECUTE IMMEDIATE

Page 49: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

49/51

Exemple

…EXEC SQL BEGIN DECLARE SECTION;char tup[] = “INSERT INTO Emp VALUES (?,?,?,?);

char eno[3], enom[15], titre[10], ville[12];EXEC SQL END DECLARE SECTION;EXEC SQL PREPARE S1 FROM :tup;/* obtenir les valeurs de :eno, etc. */

EXEC SQL EXECUTE S1 USING :eno, :ename, :titre, :ville;

Page 50: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

50/51

Tampons dynamiques

Si le résultat d'une requête est une ensemble, alors utiliser des tampons dynamiques

Définire des tampons dynamiques similaires à leurs contreparties statiques, mais utiliser USING pour fournir les paramètres de la rêquete

EXEC SQL DECLARE <cursor-name> CURSOR FOR stmt;

EXEC SQL OPEN <cursor-name> USING :var1 [,…,:varn];

EXEC SQL FETCH <cursor-name> INTO :out1 [,…,:outk];

EXEC SQL CLOSE <cursor-name> ;

Page 51: Vues. 2/51 Vues n Table deriveé des tables existants (table de base) u Accès adapte a besoin d'application (couche externe) u Stockage des requêtes u

51/51

Exemple…EXEC SQL BEGIN DECLARE SECTION;char resp[10]; /* input: responsable */char pno[3]; /* output: numéro du projet */real avg-dur; /* output: durée moyenne */char s[] = “SELECT Pno, AVG(Dur) FROM Travaille_sur WHERE Resp = ‘?’ GROUP BY Pno, Eno HAVING COUNT(*) > 2”;

EXEC SQL END DECLARE SECTION;EXEC SQL PREPARE S1 FROM :s;EXEC SQL DECLARE durée CURSOR FOR S1;/* obtenir la valeur du :resp */

EXEC SQL OPEN durée USING :resp;EXEC SQL WHENEVER NOT FOUND DO BREAK;while(1) {EXEC SQL FETCH FROM durée INTO :pno, :avg-durtraiter le tuple;

}EXEC SQL CLOSE durée …