PARTIE I : L`environnement d`Oracle - Formation continue 2004-2005

publicité
DESS IGSI Formation continue
INGENIERIE ET GESTION DES SYSTEMES D'INFORMATION
Bases de données
PARTIE I : L’environnement d’Oracle ................................................................................... 3
TD 2 ................... Traduction de règles de gestion à l'aide de déclencheurs Bases de Données
3
Objectifs ..............................................................................................................................................3
Environnement ...................................................................................................................................3
Actions ................................................................................................................................................3
PARTIE II : Développement d’applications clientes avec Developper 2000 ......................... 7
TD 3 ................................................................ Le concept de formulaire dans Developer 2000
7
1 Rappel : Les trois principaux objets d’un module ......................................................................7
Bloc (Block)................................................................................................................................................... 7
Elément (Item) ............................................................................................................................................... 7
Canevas (Canvas) ........................................................................................................................................... 7
2 Création d'un formulaire basique .................................................................................................8
3 Création d’un formulaire comportant un sous formulaire ........................................................9
4 Exercice ..........................................................................................................................................10
TD 4 ..............
Déclencheurs d'applications et listes de valeurs Création de boutons et de
déclencheurs associés écrits en PL/SQL .......................................................................................... 12
1 Rappel : la gestion des clés étrangères ........................................................................................12
2. Exercice 1 : création d’un formulaire exploitant une LOV .....................................................12
Action 1 : ..................................................................................................................................................... 12
Action 2 : ..................................................................................................................................................... 13
Action 3 : ..................................................................................................................................................... 14
3. Exercice 2 : améliorer l'utilisation d'une LOV .........................................................................14
4. Rappel : Les déclencheurs (triggers) .........................................................................................15
Exemple : Contrôler l’affichage d’une LOV dans un formulaire ................................................................ 16
5. Exercice 3 : gestion de l’affichage automatique d’une LOV ...................................................16
Solution 1 : ................................................................................................................................................... 16
Solution 2 : ................................................................................................................................................... 16
Solution 3 : ................................................................................................................................................... 17
6. Exercice 4 : gestion de LOV dynamiques ..................................................................................17
TD 5 .............. Synchronisations entre les Blocs de données (FORMS) et la Base de Données
19
Rappel : notion de Bloc basé / non basé.........................................................................................19
1 Remplir le tableau d’un Bloc avec des données stockées dans la Base de données .................................. 19
2 Modifier la Base de données via le tableau d’un Bloc .............................................................................. 20
Exercice I : Contrôler l’affichage des valeurs dans un bloc ........................................................20
Exercice II : Création d’un bloc non basé avec les boutons Valider et Annuler .......................21
Execercie III : Afficher des données calculées dans un Elément non basé ................................22
Solution 1 : ................................................................................................................................................... 22
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation continue
Solution 2 : ................................................................................................................................................... 23
Exercice IV : Sélectionner dynamiquement les éléments affichés dans un Bloc .......................23
Exercice V : Utilisation d'alertes ....................................................................................................24
Exercice VI : Gestion d’une contrainte d’intégrité au niveau de l’application .........................24
Exercice VII : création d’une contrainte sur un item ..................................................................26
Exercice VIII : question de cours ...................................................................................................26
TD 6 ...
Gestion spécifique des blocs maître/détail lorsqu'il n'y a pas de jointure directe
entre les blocs. Gestion du remplissage des blocs détails à l'aide de déclencheurs écrits en
PL/SQL .............................................................................................................................................. 27
I Création d’un bloc non basé affichant des données ...................................................................27
II Ajout d'éléments calculés ............................................................................................................30
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
2
PARTIE I : L’environnement d’Oracle
TD 2 Traduction de règles de gestion à l'aide de
déclencheurs Bases de Données
Objectifs
Pratique du langage PL/SQL
Conception de déclencheurs Bases de Données
Environnement
Voici le schéma Oracle simplifié de la base de données relatif à la Coupe du Monde de football
1998, modifié :
EQUIPES ( NE, NATIONALITE, PALMARES )
JOUEURS ( NJ, NOM, PRENOM, POSITION, MAILLOT, NE, NB_MATCH_EXPULSE
)
MATCHS ( NM, LIEU, DATE_R, NE_ RECEVANTE, NE_DEPLACANTE, ENJEU,
SCORE_RECEVANTE,
SCORE_
DEPLACANTE,
SCORE_VALIDE)
PARTICIPANTS (NJ, NM, NB_BUTS, CARTON_JAUNE, CARTON_ROUGE )
Règles de gestion



Lorsqu'un joueur obtient 2 cartons jaunes au cours d'un match, il reçoit un carton rouge.
Lorsqu'un joueur reçoit un carton rouge, il est expulsé pour les deux matchs à venir.
Evidemment, un joueur expulsé ne doit pas pouvoir être sélectionné pour participer à un match.
Afin de faire respecter ces règles, les deux attributs suivants ont été rajoutés respectivement
dans les tables JOUEURS et MATCHS :

NB_MATCH_EXPULSE indique à tout moment pour combien de matchs le joueur est encore
expulsé depuis le dernier match effectivement joué (le score est validé) par sont équipe.

SCORE_VALIDE vaut 1 si le match a été effectivement joué.
Actions
Proposez les déclencheurs nécessaires pour faire respecter ces règles de gestion.
1. Créez sous votre compte votre propre base de donnée à l'image du schéma ci-dessus.
2. Utilisez le Schema Manager pour créer vos déclencheurs.
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
3
Nous vous conseillons d'exécuter la requête SQL générée (create or replace trigger) sous le
Worksheet pour détecter les éventuelles erreurs de syntaxe.
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
4
Solution
Action 3.1 :
Il faut créer quatre déclencheurs.
Le premier est associé à la table PARTICIPANTS sur mise à jour du nombre de cartons
jaunes. Si ce nombre atteint 2, le nombre de cartons rouges est mis à 1.
Le deuxième déclencheur est associé à la table PARTICIPANTS sur mise à jour du nombre de
cartons rouges. Si ce nombre atteint 1, l'attribut NB_MATCH_EXPULSE de la table JOUEURS est
mis à 3 pour le joueur en question.
Le troisième déclencheurs est associé à la table MATCHS. Lorsque l'attribut
SCORE_VALIDE prend la valeur 1, on décrémente de 1 l'attribut NB_MATCH_EXPULSE pour
tous les joueurs expulsés des deux équipes participantes.
Le quatrième déclencheurs est associé à la table PARTICIPANTS. Lorsque l'on tente d'insérer
une ligne dans cette table, l'insertion est refusée si le joueur en question est expulsé.
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
5
Action 3.2 :
CREATE OR REPLACE TRIGGER "MONDIAL"."EXPULSER_jaune"
BEFORE INSERT OR UPDATE OF "CARTON_JAUNE" ON "MONDIAL"."PARTICIPANTS"
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
BEGIN
IF :new.carton_jaune = 2
THEN
:new.carton_rouge := 1;
virez_le(:new.nj);
/* dbms_output.put_line('joueur '||:o.nj||' expulsé'); */
END IF;
END;
CREATE OR REPLACE TRIGGER "MONDIAL"."EXPULSER_rouge"
BEFORE INSERT OR UPDATE OF "CARTON_ROUGE" ON "MONDIAL"."PARTICIPANTS"
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
WHEN (new.carton_rouge=1)
BEGIN
update joueurs
set NB_MATCH_EXPULSE = 3
where nj = :old.nj;
END;
CREATE TRIGGER "MONDIAL".Expuls_moins_un
AFTER UPDATE OF "SCORE_VALIDE" ON "MONDIAL"."MATCHS"
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
WHEN (new.score_valide=1)
begin
update joueurs
set NB_MATCH_EXPULSE = NB_MATCH_EXPULSE - 1
where NB_MATCH_EXPULSE >= 1
and ne in (:new.ne_deplacante, :new.ne_recevante);
end;
CREATE or replace TRIGGER "MONDIAL".ne_peut_participer
BEFORE INSERT ON "MONDIAL"."PARTICIPANTS"
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
declare
virer number := 0 ;
begin
select 1 into virer
from joueurs
where nj = :new.nj
and NB_MATCH_EXPULSE >= 1;
if virer = 1 then
raise_application_error(-20101, 'Ce joueur est exclu');
end if;
exception WHEN_NO_DATA_FOUND then
null;
end;
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
6
PARTIE II : Développement d’applications clientes
avec Developper 2000
TD 3 Le concept de formulaire dans Developer 2000
1 Rappel : Les trois principaux objets d’un module
Un formulaire est un élément interactif qui permet d’insérer, consulter et/ou mettre à jours des
n-uplets stockés dans une base de données. ORACLE propose un environnement de développement
permettant de concevoir de tels formulaires appelé Developer 2000, qui s’appuie lui même sur un
environnement de plus base niveau appelé FORMS. Dans cet environnement, les formulaires sont
gérés au travers de modules. Chaque module constitue un client du serveur base de données
ORACLE.
Developer 2000 propose trois outils appelés Form Builder, Form Compiler et Forms
Runtime, permettant respectivement de concevoir des formulaires, générer le code permettant
d’exécuter ces formulaires dans l’environnement d’un système d’exploitation donné (Windows,
Unix, IBM ...) et d’exécuter ce code. Afin de faciliter le développement, Forms Builder permet
d’exécuter directement les formulaires en cours de conception, en vue de les tester. Nous
utiliserons donc principalement cet outil.
Un module est principalement constitué des 3 éléments suivants :
Bloc (Block)
Un bloc est une structure logique à laquelle peut être associée une table ou une vue de la
base de données (dans ce cas on dit qu’il est basé). Un bloc est lui même constituée d’items.
Il peut être créé manuellement ou automatiquement. Un bloc peut être définit en mono ou
en multi-lignes. Pour un bloc basé, Forms prend en charge toutes les interactions avec la
base.
Elément (Item)
Un Item sert à présenter des données ou à déclencher des commandes Forms ou des Triggers
en fonction de son type. Par exemple, un item de type texte permet d’afficher un attribut du
bloc auquel il appartient, si ce bloc est basé sur une table ; un item de type bouton permet de
déclencher des actions comme passer au n-uplet suivant dans le bloc courant. Un item de
type texte peut être simplement consultable ou consultable et modifiable. De plus, un item
peut être visible ou invisible. Pour être visible, il doit être localisé sur un canevas.
Canevas (Canvas)
Un canevas est une surface sur laquelle sont positionnés des items, graphiques ou textes
destinés à être affichés à l’écran au travers d’une fenêtre.
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
7
La figure 1 représente un formulaire basique permettant de consulter et modifier les n-uplets
de la table JOUEURS. Ce formulaire est géré au travers du module MODULE11 constitué d’un
bloc appelé JOUEURS basé sur la table JOUEURS. Ce bloc comporte 4 items de type texte
permettant d’afficher respectivement les N°, Nom, Prénom et N° d’équipe des joueurs. Tous les
items sont localisés sur le canevas CANEVAS2, dont la fenêtre est représentée sur la figure.
Ce formulaire a été généré automatiquement, mais l’emplacement des items peut être modifié
directement en cliquant sur les objets représentés dans la fenêtre du canevas. De même les
propriétés des éléments du module ainsi généré peuvent être modifiées au travers de la fenêtre
propriété. Par exemple pour interdire la misa à jour des N° des joueurs, on peut sélectionner l’item
NJ, puis cliquer sur le bouton de droite de la souris pour faire apparaître les propriétés de cet item
comme illustré figure 2. La propriété interrogation seulement peut alors être mise à vrai.
Figure 1 : Un module et la fenêtre du canevas correspondant.
Figure 2 : propriétés de l’item NJ
2 Création d'un formulaire basique
Le TD utilise la base de donnée Mondial. Vous pouvez consulter son schéma à l’aide du
Schema Manager ou dans le Navigateur (Objets de la base de données) si vous êtes connectés..
Créer le formulaire permettant de consulter les joueurs et de les modifier.
Lancer Oracle/Forms and Reports/Form Builder et utiliser les assistants. Vous devez au
passage cliquer sur le bouton parcourir pour sélectionner la table JOUEURS. Cette action va
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
8
déclencher une connexion à ORACLE pour contrôler que vous avez accès au schéma de la base de
données. Choisissez les colonnes qui vous intéressent puis demandez à utiliser l’assistant de
présentation.
Cliquer sur le bouton feu vert pour générer et tester le code du nouveau module (client).
Cliquer sur le bouton exécuter l’interrogation pour visualiser les joueurs.
Modifier les propriétés de l’item NOM pour interdire la mise à jour du nom des joueurs.
Jouer avec la fenêtre et le canevas.
3 Création d’un formulaire comportant un sous formulaire
Créer le formulaire permettant d’afficher les équipes avec leurs joueurs respectifs. Le module
correspondant sera composé de deux blocs dont un bloc maître et un bloc esclave (voir figure 3). Le
bloc maître est le bloc EQUIPES. Il pilote l’affichage des n-uplets dans le bloc esclave qui est le
bloc JOUEURS. En effet, le bloc JOUEURS ne doit afficher que les joueurs de l’équipe en cours
dans le bloc EQUIPES. Ainsi les deux blocs sont reliés par une relation dont le but est d’exprimer
la condition de jointure entre les deux tables : EQUIPES.NE = JOUEURS.NE. Le bloc EQUIPES
est un bloc de type formulaire qui affiche un n-uplet à la fois, tandis que le bloc JOUEURS est un
bloc de type table. On fera en sorte que ce dernier affiche 11 joueurs et possède un ascenseur.
Créer ce formulaire en utilisant les assistants comme suit. Créer tout d’abord un bloc basique
pour la table EQUIPES comme précédemment. Ajouter ensuite un bloc pour la table joueurs :
cliquer sur l’élément blocs de données pour le sélectionner, puis cliquer sur le bouton « + » pour
ajouter un bloc et demander à utiliser l’assistant. N’oubliez pas de sélectionner la colonne NE à la
création du bloc Equipe sans quoi la jointure ne pourrait pas être réalisée. Par contre il n’est pas
nécessaire d’afficher cette colonne puisqu’elle est déjà renseignée dans le bloc EQUIPES.
Si la liaison entre les deux blocs ne s’est pas faite automatiquement, double cliquez sur le
composant relation du bloc EQUIPES, sélectionnez le bloc joueurs comme bloc esclave et entrez la
condition de jointure comme sur la figure 4.
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
9
Figure 3 : formulaire avec un bloc maître et un bloc détail
blocs
Figure 4 : Création de la relation entre 2
Remarquez la création de deux déclencheurs destinés à la synchronisation de l’affichage dans
les deux blocs.
Remarques :
 Le déclencheur ON-POPULATE-DETAILS remplit le bloc détail à chaque changement de
ligne dans le bloc maître. Si le code de ce déclencheur est altéré, la synchronisation entre
les deux blocs ne se fait plus. Dans ce cas, nous suggérons de supprimer la relation (ce qui
a pour effet de supprimer les déclencheurs associés), et de la recréer.
 Le déclencheur PRE-DELETE exécute un code redondant avec la contrainte d’intégrité
référentielle déclarée dans la base de données pour l’attribut NE de la table JOUEURS.
Vous pouvez le supprimer.
4 Exercice
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
10
Concevoir des blocs simples de gestion pour chaque relation de votre base Mondial et de
gestion pour chaque relation de la base Mondial du compte Mondial. Vous disposerez ainsi de
moyens personnels pour consulter et mettre à jour facilement les deux bases.
Concevoir des blocs Maîtres Détails
-
Equipes  Joueurs (de chaque équipe) Participants (de chaque joueur)
-
Matchs  Participants (de chaque match)
-
Equipes  Matchs (que les équipes soient recevantes ou déplaçantes)  Participants (de
chaque match de chaque équipe)
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
11
TD 4
Déclencheurs d'applications et listes de valeurs
Création de boutons et de déclencheurs associés
écrits en PL/SQL
1 Rappel : la gestion des clés étrangères
Les clés étrangères sont utilisées pour relier les tables entre elles. Les clés étrangères posent
généralement deux problèmes à l’utilisateur final :
1- elles ne peuvent contenir que des valeurs existant dans la table référencée (contrainte
d’intégrité référentielle). En effet une clé étrangère contenant une valeur qui n’existe pas
dans la table référencée n’a pas de sens.
Par exemple : si l’attribut NE de la table Joueurs contient une valeur qui n’existe pas dans la
table Equipes, c’est équivalent à dire que ce joueur appartient à une équipe qui n’existe pas.
2- les clés sont souvent peu parlantes pour l’utilisateur final.
Par exemple : quelle est la nationalité de l’équipe 3 ? quelle est la nationalité de l’équipe 2 ?
Dans le cas d’un formulaire avec sous formulaire ces problèmes sont souvent inexistants. Par
exemple, le formulaire Equipes_Joueurs créé au TD précédent constitue le moyen idéal pour saisir
une équipe avec tous ses joueurs. La clé étrangère NE de la table JOUEURS est renseignée
automatiquement en fonction de la clé de l’équipe courante dans le formulaire principal.
Dans le cas d’un formulaire simple, ces deux problèmes peuvent être résolus en utilisant un
objet "liste de valeurs" (LOV pour List Of Values) dans le module :
Une LOV est une interrogation permettant d’afficher l’ensemble des valeurs possibles et d’en
sélectionner une. De plus, une LOV permet d’associer à ces valeurs des information plus parlantes
qu’une valeur de clé (par exemple, nationalité de l’équipe).
2. Exercice 1 : création d’un formulaire exploitant une LOV
1. Créer au moyen des assistants un formulaire simple pour la table PARTICIPANTS.
Cette table contient deux clés étrangères : NJ et NM.
2. Création d’une LOV pour NJ :
Double cliquez sur l’objet LOV de votre module pour créer la LOV et sélectionnez l’assistant.
Renommez la LOV créée ‘LOV_NJ’
Actions impliquées par la création d’une LOV
Action 1 :
Création d’une requête associée à la LOV. Cette requête permet de construire dynamiquement
les valeurs de cette liste lorsque la LOV est invoquée. Cette requête est stockée dans un composant
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
12
du module appelé groupe d’enregistrements(record group ou group dans la documentation). La
figure 1 illustre la création d’un groupe d’enregistrement. La requête associée sélectionne les n° des
joueurs de la table JOUEURS, mais aussi les noms et prénoms des joueurs, qui sont plus parlants
pour l’utilisateur final.
Figure 1 : La requête associée à une LOV
Action 2 :
Spécification des colonnes de la requête qui seront affectées à un élément d’un bloc du
module. Cette spécification se fait au moyen de la propriété de "correspondance de colonne" du
composant LOV en cours de création. Vous pouvez consulter ou modifier cette spécification en
cliquant sur le bouton "Suite" de cette propriété. Dans notre cas, il faut associez la colonne NJ de la
LOV à l’élément NJ du bloc (voir Figure 2).
Figure 2 : Association de la colonne NJ de la liste à l’élément NJ du bloc
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
13
Action 3 :
Association de la LOV à l’élément récepteur du bloc. Cela se fait au moyen de la propriété
LOV de l’élément. Dans notre cas, la propriété LOV de l’item NJ a été modifiée pour signaler
qu’une LOV est associée à cet item (voir Figure 3).
Figure 3 : affecter une LOV à un Item
3. Tester le module. Lorsque l’on clique sur l’item NJ, la barre d’état indique qu’une liste de
valeurs est disponible. Pour afficher cette liste appuyez sur la touche fonction F9.
Remarque
Pour connaître les touches fonction de Forms et leur rôle, activez le menu Aides/Touches.
3. Exercice 2 : améliorer l'utilisation d'une LOV
Vous pouvez remarquer que la LOV créée pour NJ n'est pars facile à exploiter par l'utilisateur
final. En effet, pour sélectionner un joueur par son nom, il faut faire défiler toute la liste avec un
ascenseur. Or, la fenêtre d'affichage d'une LOV comporte un outil de recherche. Cet outil
s'applique exclusivement à la première colonne affichée dans la LOV. Ainsi, il serait souhaitable de
réécrire la requête associée à la LOV afin d'afficher en premier le nom du joueur. La requête
modifiée et la LOV associée sont affichés ci-dessous. Attention, il est nécessaire de trier le résultat,
pour que les outils de recherche fonctionnent.
SELECT ALL JOUEURS.NOM, JOUEURS.PRENOM, JOUEURS.NE, JOUEURS.NJ
FROM JOUEURS
ORDER BY 1
4. Créez une LOV pour NM.
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
14
4. Rappel : Les déclencheurs (triggers)
Il existe plusieurs solutions pour contrôler l’affichage de la LOV associée à un item (élément),
afin d’éviter à l’utilisateur non averti d’avoir à utiliser la touche F9. Ces solutions utilisent toutes
des déclencheurs provoquant l’exécution d’un programme écrit en PL/SQL lorsqu’un événement
intervient.
Un déclencheur (trigger) est définit par trois principaux composants :
-
son type (événement associé) ;
son code (bloc PL/SQL);
son niveau de définition (objets auquel il est associé).
Les objets auxquels il est possible d’associer des déclencheurs sont les modules de type
"application forms", les blocs et les éléments des blocs (items).
Les événements permettant d’activer un déclencheur dépendent du type d’objet auquel est
associé le déclencheur (module, bloc ou item). Ces événements sont classés en cinq catégories :
-
PRE- se déclenche avant une action forms ;
POST- se déclenche après une action forms ;
WHEN- se déclenche au même moment qu’une action forms (permet d’augmenter les
fonctionnalités de forms) ;
ON- se déclenche à la place d’une action forms ;
KEY- se déclenche à la place d’une fonction touche standard.
Pour obtenir la liste de ces événements avec leur signification précise utiliser la commande
de l’aide de developper/2000 Aide/Form builder Rubrique d’aide/Référence PL/SQL /Déclencheurs.
Vous pouvez aussi passer par la commande rechercher du menu Aide/Form builder Rubrique
d’aide.
Rappelons que la structure d’un bloc PL/SQL est la suivante :
[DECLARE]
- variables, constantes, curseurs, expressions utilisateurs
BEGIN
- Ordres SQL
- Instructions de contrôle PL/SQL
[EXCEPTIONS]
- Traitements à effectuer lors des erreurs
END ;
Chaque instruction à l’intérieurs du bloc se termine par un point virgule.
Comme indiqué ci-dessus, un bloc PL/SQL comporte 3 sections (DECLARE, BEGIN et
EXCEPTIONS) parmi lesquelles seule la section BEGIN est obligatoire. Dans le cas ou les blocs
DECLARE et EXCEPTIONS sont omis, les lignes BEGIN et END sont facultatives.
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
15
Exemple : Contrôler l’affichage d’une LOV dans un formulaire
DECLARE rep BOOLEAN;
BEGIN
IF :participants.nj is null THEN
bell;
rep := show_lov ('LOV4');
END IF;
END;
Dans le code ci-dessus, rappelons que dans l’expression :participants.nj les deux points
":" permettent de désigner le bloc PARTICIPANTS et non la table PARTICIPANTS.
5. Exercice 3 : gestion de l’affichage automatique d’une LOV
Trois solutions vous sont proposées pour afficher la LOV associée à NJ.
comportent des inconvénients.
Certaines
Solution 1 :
Création d’un déclencheur WHEN-MOUSE-DOUBLECLICK pour l’item NJ avec le code cidessous. Pour créer ce déclencheur cliquez sur le + de l’item NJ afin de faire apparaître l’objet
déclencheur. Double cliquez sur cet objet puis choisissez l’événement voulu dans la fenêtre du
déclencheur avant d’entrer le code PL/SQL. Cliquez sur le bouton compiler de la fenêtre du
déclencheur pour tester la syntaxe de votre code.
DECLARE rep BOOLEAN;
BEGIN
bell;
rep := show_lov ('LOV_NJ');
END;
/* LOV_NJ est le nom de la LOV */
Remarque : show_lov est une commande très utile de PL/SQL. Il en existe bien d’autres de
ce type. Il est impossible de les connaître toutes par cœur. Pour les retrouver et apprendre à les
utiliser, exploitez la commande d’aide Aide/Form builder Rubrique d’aide/Référence
PL/SQL /Packages intégrés de Form Builder/Liste alphabétique.
Testez ce déclencheur. L’inconvénient de cette solution est que l’utilisateur doit connaître la
convention qui consiste à double cliquer sur l’item pour faire apparaître la LOV.
Solution 2 :
Création d’un déclencheur PRE-TEXT-ITEM avec le code ci-dessous.
declare
recstat
VARCHAR2(20) := :System.record_status;
rep boolean;
BEGIN
IF ( recstat <> 'NEW' and recstat <> 'INSERT' ) THEN
RETURN;
END IF;
rep:=show_lov('LOV_NJ');
END;
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
16
Solution 3 :
Création d’un bouton pour afficher la liste, avec un déclencheur WHEN-BUTTON-PRESSED
qui contiendra le même code que précédemment.
Double cliquez sur l’objet éléments, puis dans la propriété type d’élément de ce nouvel
élément choisissez bouton de commande. Dans la propriété libellé de cet élément introduisez la
chaîne '\/' (back-slach, slash). Renommez cet item Liste_Joueurs.
Ajoutez le déclencheur.
Modifiez le canevas pour que le bouton prenne l’aspect d’une boîte liste à côté de NJ.
Attention, pour que ce bouton puisse être utilisé, il faut que son item soit placé en premier
dans la liste des items du bloc. Observez les anomalies d’utilisation de ce bouton. Ces anomalies
peuvent être évitées en positionnant la propriété obligatoire de NJ à faux.
6. Exercice 4 : gestion de LOV dynamiques
En fonction du contexte de l’application, il peut être utile qu’une LOV n’affiche que les
données pertinentes d’une table. Par exemple, une fois le numéro de match saisi dans une ligne du
formulaire de la table participants, il serait souhaitable que la LOV permettant de saisir un numéro
de joueur restreigne l’affichage aux joueurs d’une des équipes participant au match choisi. Ainsi, la
requête associée à cette LOV doit être modifiée automatiquement, à chaque appel de la LOV, afin
de prendre en compte le numéro de match saisi dans l’élément NM courant du bloc
( :PARTICIPANTS.NM).
Pour
cela,
nous
allons
utiliser
la
fonction
POPULATE_GROUP_WITH_QUERY décrite ci-dessous.
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
17
POPULATE_GROUP_WITH_QUERY :
Lorsque vous utilisez cette procédure interne, l'interrogation indiquée devient
l'interrogation par défaut du groupe, et s'exécute chaque fois que la procédure interne
POPULATE_GROUP est appelée. Si l'instruction SELECT échoue, Form Builder retourne
un numéro d'erreur ORACLE. Si l'interrogation réussit, cette procédure interne retourne 0
(zéro). Les lignes extraites remplacent les lignes du groupe d'enregistrements.
Syntaxe
FUNCTION POPULATE_GROUP_WITH_QUERY
(id_groupeenreg RecordGroup,
interrogation VARCHAR2);
FUNCTION POPULATE_GROUP_WITH_QUERY
(nom_groupeenreg VARCHAR2,
interrogation VARCHAR2);
5. Modifiez le code du déclencheur associé au bouton de la LOV LOV_NJ comme suit :
DECLARE
rep boolean;
BEGIN
/* L'exemple ci-dessous montre comment remplacer l’interrogation
** d’un groupe d'enregistrements lors de l'exécution : */
IF (Populate_Group_With_Query
('LOV_NJ',
'SELECT NOM, PRENOM, NE, NJ
FROM JOUEURS
where ne in (select ne_recevante
from matchs
where nm = :participants.nm
union
select ne_deplacante
from matchs
where nm = :participants.nm)
order by 1 '))
<> 0 THEN
RAISE form_trigger_failure;
END IF;
rep:=show_lov('LOV_NJ');
END;
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
18
TD 5 Synchronisations entre les Blocs de données
(FORMS) et la Base de Données
Rappel : notion de Bloc basé / non basé
Un Bloc basé est destiné à permettre la consultation et/ou la mise à jours de données issues
d'une table stockée dans la base de données ou d'une vue. Le nom de la source de données est une
des propriétés Base de données du Bloc. Au niveau du client Form, le bloc se comporte comme un
tableau de lignes, les enregistrements (records), capables d'accueillir des n-uplets issues de la source
de données. La structure de ces n-uplets est décrite par les éléments basés du bloc, ceux dont la
propriété Elément base de données à la valeur Oui.
1 Remplir le tableau d’un Bloc avec des données stockées dans la Base de données
Au démarrage de l'application cliente, ce tableau d'enregistrements est vide. La procédure
prédéfinie "EXECUTE_QUERY" permet d'extraire les données de la source pour remplir le tableau
du bloc actif. Cette procédure peut être activée par l'utilisateur en utilisant l'un des moyens suivants
: la commande du menu "Interrogation/Exécuter" ; le bouton "exécuter interrogation" ; la touche
"F8". Elle peut aussi être appelée dans un déclencheur d'application.
Par défaut, l'interrogation permettant d'instancier le tableau d'un bloc a la structure suivante :
SELECT
ALL E1, E2,…,En
INTO
:E1, :E2,…, :En
FROM
source ;
où :E1, :E2,…, :En sont les noms des Eléments basés du Bloc et source est le nom de la
source de données (table ou vue) du Bloc.
Cette requête porte sur une seule table. Elle peut comporter une clause "WHERE" si
l'utilisateur a utilisé l'un des moyens suivants : la commande du menu "Interrogation/Entrer" ; le
bouton "entrer interrogation" ou la touche "F7", avant d'exécuter l'interrogation. Il est aussi possible
de spécifier une clause "WHERE" par défaut pour un Bloc, via la propriété Base de données du bloc
nommée "WHERE". Cette propriété peut être modifiée par programmation dans un déclencheur en
utilisant la procédure "SET_BLOCK_PROPERTY spécifiée ci-dessous :
SET_BLOCK_PROPERTY
'prédicat');
('NOM_DU_BLOC',
DEFAULT_WHERE,
Il peut arriver que l’action EXECUTE_QUERY retourne le message d'erreur suivant :
"Exécution de l'interrogation impossible". Cela peut être du au fait que l'un des Eléments basés du
Bloc porte un nom ne correspondant pas à un attribut de la source de données. Cela peut aussi être
du à une erreur dans la clause WHERE. Pour voir le texte de la requête qui a été envoyée au serveur
base de données, appeler la commande du menu "Aide/Afficher erreur".
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
19
2 Modifier la Base de données via le tableau d’un Bloc
Par défaut, l’utilisateur a le droit de modifier, insérer ou supprimer des lignes dans le tableau
correspondant à un Bloc de données. Il est possible de restreindre les droits de mise à jour d’un
utilisateur, au niveau de l’application Form, via les propriétés Base de données Insertion autorisée,
Mise à jour autorisée et Suppression autorisée. Ces propriétés peuvent être réglées au niveau du
Bloc ou de ses Eléments.
Si l'application lui en donne l'autorisation, l'utilisateur peut insérer, modifier des lignes dans le
tableau d'un bloc. La procédure prédéfinie "COMMIT_FORM" permet de transférer les données
modifiées du tableau du bloc vers la source de données (dans la base de données). Cette procédure
peut être activée par l'utilisateur en utilisant l'un des moyens suivants : la commande du menu
"Action/Enregister" ; le bouton "Enregister" ; la touche "F10". Elle peut aussi être appelée dans un
déclencheur d'application.
Etant donné que les mises à jours dans le tableau du bloc, sont effectuées indépendamment de
la Base de données, la commande transactionnelle ROLLBACK ne peut pas fonctionner pour
annuler les mises à jour effectuées au travers d'une application Form. La seule solution pour
annuler les mises à jour, consiste à vider le tableau du Bloc puis à ré-exécuter l’interrogation du
Bloc. Form Builder propose les procédures suivantes permettant respectivement de vider tous les
Blocs, vider le Bloc actif, vider l’enregistrement actif, vider l’Elément actif :
CLEAR_FORM (mode_commit) ;
CLEAR_BLOCK (mode_commit) ;
CLEAR_RECORD ;
CLEAR_ITEM ;
mode_commit admet plusieurs options (cf. documentation). L’option NO_VALIDATE permet
de vider le ou les blocs sans transmettre les mises à jour à la base de données.
Exercice I : Contrôler l’affichage des valeurs dans un bloc
Ouvrir l’application Equipes_Joueurs comportant un bloc maître pour la table EQUIPES et un
bloc esclave pour la table JOUEURS (cf. TD précédents).
Créer un déclencheur WHEN-NEW-FORM-INSTANCE affecté au module. Ce bloc
contiendra le code suivant :
BEGIN
EXECUTE_QUERY;
/* REMARQUE
** Il aurait été possible de Simuler l'action sur la touche F8 en
** utilisant la rocédure interne : DO_KEY.
** Exemple :
**
Do_Key('EXECUTE_QUERY');
*/
END;
Exécuter la forme. Que se passe-t-il ?
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
20
Il se peut que le Bloc actif ne soit pas le bloc EQUIPES au moment ou l'application Form
démarre. Le Bloc actif à l’ouverture de l’application est le premier Bloc qui apparaît dans la liste
des Blocs de données du module Form. Deux solutions sont possibles pour activer en premier le
Bloc EQUIPES :
a) Le mettre en premier dans l’élément Blocs de données en le faisant glisser avec la souris.
b) Ajouter dans le déclencheur WHEN-NEW-FORM-INSTANCE la commande :
Go_Block('EQUIPES');
avant la commande :
EXECUTE_QUERY;
Tester les deux solutions.
A titre d’exercice, mettez un prédicat erroné (ex : ‘trurlututu’) dans la propriété Clause
WHERE ou Clause ORDER BY d’un Bloc, puis observez la requête SQL envoyée au serveur via la
commande du menu "Aide/Afficher erreur".
Exercice II : Création d’un bloc non basé avec les boutons Valider et Annuler
Objectif : créer deux boutons valider et annuler pour les blocs imbriqués EQUIPES et
JOUEURS.
Créer un bloc appelé "COMMANDES" sans utiliser les assistants. Signaler qu’il ne s’agit pas
d’un bloc basé sur la base de données (cf. Figure 1 ). Y ajouter deux boutons dotés chacun d'un
déclencheur WHEN_BUTTON_PRESSED permettant respectivement de valider une transaction
avec ses mises à jour ou d’abandonner la transaction. Affecter à ces boutons des libellés appropriés.
Utiliser la commande d’aide pour trouver les instructions PL/SQL que le bouton VALIDER doit
exécuter. N’oubliez pas d’afficher ces boutons dans le canevas (ou l’onglet) courant.
Figure 1 : Création d’un bloc non basé
Le code que doit exécuter le bouton ANNULER est le suivant :
message('abandon des mises à jour');
--rollback; /* ne marche pas dans un déclencheur Form*/
--raise form_trigger_failure; /* ne marche pas dans ce cas */
Go_Block ('EQUIPES');
Clear_Block(No_validate);
Go_Block ('EQUIPES');
Execute_Query;
Remarque 1 :
La commande MESSAGE permet d'afficher un message à l'utilisateur. L'inconvénient de cette
commande est le suivant : selon le contexte, le message s'affiche soit en bas de l'écran dans la barre
d'états, soit dans une fenêtre spécifique avec un bouton OK. La deuxième solution est préférable,
mais on ne peut pas l'imposer.
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
21
Une autre solution consiste donc à utiliser la notion d'alerte pour envoyer des messages à
l'utilisateur (cf. Exercice V infra).
Remarque 2 :
Après une mise à jour dans le Bloc JOUEURS, le bouton Annuler génère un message
"Voulez-vous enregistrer les mises à jours". Ce message provient du fait des synchronisations
maître/détail avec le Bloc EQUIPES. Le même message s'affiche après une mise à jour dans le Bloc
JOUEURS puis un changement d'équipe dans le Bloc maître. Pour éviter cet inconvénient, il faut
utiliser l'instruction Clear_Form qui ne contraint pas l'application à revenir dans le Bloc EQUIPES.
Par contre, cette instruction a pour effet de vider aussi les Blocs des autres onglets.
Clear_form (no_validate); /* vide le bloc */
Go_Block('EQUIPES');
/* se positionnne sur le bloc maître*/
Execute_Query;
Execercie III : Afficher des données calculées dans un Elément non basé
Ajouter au bloc JOUEURS un nouvel Elément non basé (i.e. avec la propriété "Elément de
base de données" positionnée à FAUX). Renommer cet Elément "CALCULE" et initialiser
correctement ses propriétés Canevas et Page d'onglet. Placer cet item au bon endroit dans le
canevas et lui affecter une étiquette.
Affecter à cet item un déclencheur WHEN_MOUSE_CLICK avec le code suivant :
select sum(nb_buts) into :joueurs.calcule
from participants
where nj = :joueurs.nj;
Remarque :
Si l'élément CALCULE était basé, ce déclencheur effectuerait une mise à jour dans la Base de
données.
Pensez à ajouter des buts dans la table PARTICIPANTS pour tester votre code.
Malheureusement, avec ce déclencheur, il faut cliquer sur l’item calculé pour afficher son
contenu. Pour que toutes les instances de l'Elément CALCULE se remplissent automatiquement, il
faut exécuter l’instruction SELECT pour chaque enregistrement du bloc JOUEURS.
Solution 1 :
La solution la plus simple consiste à utiliser le déclencheur Post-Query dont la spécification
est rappelée ci-dessous :
Lorsqu'une interrogation est ouverte dans le bloc, le déclencheur Post-Query est activé chaque
fois que Form Builder extrait un enregistrement d'un bloc. Il est activé une fois par enregistrement
placé dans le tableau des enregistrements du bloc.
Pour cet exemple, le déclencheur Post-Query doit être déclaré au niveau du bloc EQUIPES
avec le même code que le déclencheur précédent.
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
22
Solution 2 :
Du fait de la relation "Maître Détail" entre les blocs EQUIPES et JOUEURS, le bloc
JOUEURS est rempli par un déclencheur ON-POPULATE-DETAILS associé au bloc EQUIPES,
qui est activé à chaque changement d’équipe. Modifier ce déclencheur comme suit pour remplir les
items calculés de JOUEURS :
--- Begin default relation declare section
-DECLARE
recstat
VARCHAR2(20) := :System.record_status;
startitm
VARCHAR2(61) := :System.cursor_item;
rel_id
Relation;
--- End default relation declare section
--- Begin default relation program section
-BEGIN
IF ( recstat = 'NEW' or recstat = 'INSERT' ) THEN
RETURN;
END IF;
--- Begin JOUEURS detail program section
-IF ( (:EQUIPES.NE is not null) ) THEN
rel_id := Find_Relation('EQUIPES.EQUIPES_JOUEURS');
Query_Master_Details(rel_id, 'JOUEURS');
/* debut ajout élément calculé */
Go_Block ('JOUEURS');
First_Record;
WHILE :System.Last_Record <> 'TRUE' LOOP
select sum(nb_buts) into :joueurs.calcule
from participants
where nj = :joueurs.nj;
Next_Record;
END LOOP;
/* fin ajout élément calculé */
END IF;
--- End JOUEURS detail program section
-IF ( :System.cursor_item <> startitm ) THEN
Go_Item(startitm);
Check_Package_Failure;
END IF;
END;
-- End default relation program section
Profitez de cet exercice pour observer les autres déclencheurs associés à la relation maître
détail entre EQUIPES et JOUEURS.
Exercice IV : Sélectionner dynamiquement les éléments affichés dans un Bloc
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
23
Avant de faire cet exercice, assurez-vous que votre module possède un onglet permettant
d’afficher les participants d’un match. Si ce n’est pas le cas, ouvrez le module PARTICI¨PANTS
créé au cours du TD concernant les LOV.
Objectif : restreindre dynamiquement l’affichage dans le bloc PARTICIPANTS.
Créer un bloc non basé appelé RESTRICTION comportant un Elément (Text Item) permettant
à l’utilisateur de saisir un n° de match et deux boutons RESTREINDRE et TOUT_AFFICHER
permettant respectivement, sur un simple clic, de n’afficher que les participants du match choisi par
l’utilisateur ou de tout afficher.
Renommez l’Elément de saisie "NM".
Le code du déclencheur WHEN-BUTTON-PRESSED associé au bouton "RESTREINDRE"
est donné ci-dessous :
begin
if :restriction.nm is null then
bell;
message('Vous n''avez pas sélectionné de match !');
message('Vous n''avez pas sélectionné de match !');
else
SET_BLOCK_PROPERTY ('PARTICIPANTS', DEFAULT_WHERE,
'NM = '||:restriction.nm);
Go_Block ('PARTICIPANTS');
Execute_Query;
end if;
end;
Le code du déclencheur WHEN-BUTTON-PRESSED
"TOUT_AFFICHER" est donné ci-dessous :
associé
au
bouton
begin
SET_BLOCK_PROPERTY ('PARTICIPANTS', DEFAULT_WHERE'');
Go_Block ('PARTICIPANTS');
Execute_Query;
end;
Exercice V : Utilisation d'alertes
Une alerte est un objet rattaché à un module, permettant d'afficher un message dans une boîte
de dialogue. Ainsi, une alerte est dotée de la propriété message destinée à recevoir le message qui
doit être affiché dans la boîte de dialogue. Vous pouvez changer un message d'alerte lors de
l'exécution en lançant la procédure interne SET_ALERT_PROPERTY. Cette option vous permet de
réutiliser le même objet alerte, mais d'afficher un message différent chaque fois qu'il est appelé.
Enfin, la fonction ci-dessous permet de d'afficher la boîte de dialogue d'une alerte :
reponse
numerique */
:=
Show_Alert
('NOM_DE_L_ALERTE');
/*
reponse
est
de
type
Créer une alerte générique appelée ALERTE_GENERIQUE. Y associer le message 'Coucou'.
Créer un bouton permettant d'afficher ce message.
Exercice VI : Gestion d’une contrainte d’intégrité au niveau de l’application
Ouvrir l’application EQUIPES_JOUEURS.
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
24
Objectif : introduire une contrainte qui interdit l’insertion de plus de 14 joueurs pour une
équipe.
Créez deux déclencheurs associés au module, le premier de type PRE-COMMIT et le second
de type POST-FORMS-COMMIT.
Leur associer le code :
Declare
V_ne
V_nbj
reponse
number (11);
number;
number;
Begin
V_ne := :EQUIPES.NE;
select count(nj) into V_nbj
from joueurs
where ne = V_ne;
Set_Alert_Property('ALERTE_GENERIQUE',ALERT_MESSAGE_TEXT,'Précomit
'||V_nbj);
reponse := Show_Alert('ALERTE_GENERIQUE');
End ;
:
Exécutez le module, insérer 2 joueurs à une équipe et observez les messages :
 les joueurs ne sont pas encore insérés dans la BD au moment de l'exécution du "précommit".
Modifiez le déclencheur POST-FORMS-COMMIT pour qu’il exécute le code suivant :
Declare
V_ne
number (11);
V_nbj
number;
trop_joueurs Exception;
Begin
V_ne := :EQUIPES.NE;
select
into
from
where
count(nj)
V_nbj
joueurs
ne = V_ne;
If v_nbj > 14 Then
raise trop_joueurs;
End If;
Exception
When trop_joueurs Then
message ('plus de 14 joueurs');
bell; bell;
--ROLLBACK; /* Rappel : pas possible ici. */
Raise form_trigger_failure;
End;
Remarques :
a) Avec ce code, les joueurs insérés en trop restent affichés. L’utilisateur peut supprimer
quelques joueurs, puis tenter de revalider sa transaction.
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
25
b) Si l'on insère des joueurs dans une équipe, puis on essaie de changer d’équipe pour insérer
d’autres joueurs, Form force la validation de la transaction.
 Le code ci-dessus est correct. En effet, si la transaction n’était pas validée à chaque
changement d’équipe, le comptage du nombre de joueurs pour l’équipe en cours ne
serait pas suffisant.
Exercice VII : création d’une contrainte sur un item
Ouvrir l’application PARTICIPANTS.
Objectif : introduire une contrainte qui interdit de diminuer le nombre de buts marqués par
un joueur.
Créer un déclencheur associé à l’élément NB_BUTS de type WHEN-VALIDATE-ITEM et lui
associer le code :
Declare
old_nb_buts number;
Begin
Select
Into
From
Where
nb_buts
old_nb_buts
participants
nj = :participants.nj and nm = :participants.nm;
If :participants.nb_buts < old_nb_buts Then
message('le nombre de buts doit augmenter');
raise form_trigger_failure;
End If;
End;
Tester si la nouvelle contrainte est bien appliquée.
Exercice VIII : question de cours
Peut-on remplacer les deux contraintes d'application créées dans les exercices VI et VII par
des contraintes d'intégrité déclarées au niveau du schéma de la base de données ? Quels sont les
avantages et inconvénients des deux solutions ?
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
26
TD 6
Gestion spécifique des blocs maître/détail lorsqu'il
n'y a pas de jointure directe entre les blocs.
Gestion du remplissage des blocs détails à l'aide de
déclencheurs écrits en PL/SQL
I Création d’un bloc non basé affichant des données
On souhaite produire le formulaire de la figure 1, qui présente chaque match avec les deux
équipes impliquées et la liste des participants de chaque équipe :
Figure 1 : un formulaire non standard
Ce formulaire est constitué de 5 Blocs de données et de 2 Relations Maître-Détails :

le bloc MATCHS est basé sur la table Matchs,

les blocs EQUIPE_REC et EQUIPE_DEP sont basés sur la table Equipes et sont en relation
Maître Détails avec MATCHS avec les conditions respectives :

"Matchs.ne_recevante=Equipe_rec.ne" et "Matchs.ne_deplacante=Equipe_dep.ne".

les blocs PARTICIPANTS_REC et PARTICIPANTS_DEP sont basés sur la table Participants
et ne sont en relation avec aucun autre bloc.
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
27
Le remplissage dans des blocs PARTICIPANTS_REC et PARTICIPANTS_DEP ne peut être
géré par une Relation Maître-Détails car il n'y a pas de condition de jointure directe entre le bloc
MATCHS et ces 2 blocs. Il n'est pas non plus possible de créer une relation Détails-Détails entre les
blocs EQUIPE_REC et PARTICIPANTS_REC (resp EQUIPE_DEP et PARTICIPANTS_DEP). La
solution consiste à remplir ces 2 blocs par programmation dans le déclencheur ON-POPULATEDETAILS du block MATCHS, en le complétant de la façon suivante :
-- Note : le code en italique correspond au code généré par Form_Builder pour les
-- deux relations : 'MATCHS.MATCHS_EQUIPE_REC' et 'MATCHS.MATCHS_EQUIPE_DEP'
--- Begin EQUIPES_REC detail program section
-IF ( (:MATCHS.NE_RECEVANTE is not null) ) THEN
rel_id := Find_Relation('MATCHS.MATCHS_EQUIPE_REC');
Query_Master_Details(rel_id, 'EQUIPE_REC');
--- Début du Code à ajouter au déclencheur
--
Set_Block_Property('PARTICIPANTS_REC',DEFAULT_WHERE,
'nj in (select nj from joueurs where ne = '
||:MATCHS.NE_RECEVANTE
||') and nm = '
||:MATCHS.NM);
go_block('PARTICIPANTS_REC');
execute_query;
--- Fin du Code à ajouter au déclencheur
--
END IF;
--- End EQUIPES_REC detail program section
---- Begin EQUIPES_DEP detail program section
-IF ( (:MATCHS.NE_DEPLACANTE is not null) ) THEN
rel_id := Find_Relation('MATCHS.MATCHS_EQUIPE_DEP');
Query_Master_Details(rel_id, 'EQUIPE_DEP');
--- Début du Code à ajouter au déclencheur
--
Set_Block_Property('PARTICIPANTS_DEP',DEFAULT_WHERE,
'nj in (select nj from joueurs where ne = '
||:MATCHS.NE_DEPLACANTE
||') and nm = '
||:MATCHS.NM);
go_block('PARTICIPANTS_DEP');
execute_query;
--- Fin du Code à ajouter au déclencheur
--
END IF;
--- End EQUIPES_DEP detail program section
--
REMARQUES :
Cette solution est basée sur l'utilisation de l'instruction EXECUTE_QUERY pour
remplir les éléments des blocs PARTICIPANTS_REC et PARTICIPANTS_DEP avec les valeurs
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
28
stockées dans la base de données. Dans la logique de Form Builder, c'est la seule solution possible
pour remplir des blocs basés.
Une autre solution consiste à débaser les blocs PARTICIPANTS_REC et
PARTICIPANTS_DEP et à remplir ces blocs par programmation en envoyant des requêtes SQL
à la Base de données. Attention, les blocs étant non-basés, les mises à jours réalisées par
l'utilisateur ne sont pas prises en compte automatiquement par Form. A titre d'illustration, le
code correspondant est le suivant :
--- Begin default relation declare section
-DECLARE
recstat VARCHAR2(20) := :System.record_status; -- état du record courant
startitm VARCHAR2(61) := :System.cursor_item;
-- élément "actif"coutant
rel_id
Relation;
--- Début des déclarations des nouvelles variables pour le remplissage des
-- blocs PARTICIPANTS_REC et PARTICIPANTS_DEP
CURSOR c_rec is
SELECT
p.nj, nb_buts, carton_jaune, carton_rouge
FROM
participants p, joueurs j
where
p.nj=j.nj
and j.ne= :matchs.ne_recevante
and p.nm = :matchs.nm
ORDER BY
p.nj ;
CURSOR c_dep is
SELECT
p.nj, nb_buts, carton_jaune, carton_rouge
FROM
participants p, joueurs j
where
p.nj=j.nj
and j.ne= :matchs.ne_deplacante
and p.nm = :matchs.nm
ORDER BY
p.nj ;
--- Fin des déclarations de variables ajoutées au déclencheur
--- End default relation declare section
---- Begin default relation program section
-BEGIN
IF ( recstat = 'NEW' or recstat = 'INSERT' ) THEN
RETURN;
END IF;
--- Begin EQUIPES detail program section
-IF ( (:MATCHS.NE_RECEVANTE is not null) ) THEN
rel_id := Find_Relation('MATCHS.MATCHS_EQUIPES');
Query_Master_Details(rel_id, 'EQUIPES');
--- Début du Code à ajouter au déclencheur pour afficher PATCICIPANTS
--
Go_Block ('PARTICIPANTS_REC');
Clear_Block;
First_Record;
OPEN c_rec;
Fetch
c_rec
into
:participants.nj,
:participants_rec.nb_buts,
:participants_rec.carton_jaune,
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
29
:participants_rec.carton_rouge;
While c_rec%found Loop
Next_Record;
Fetch c_rec into
:participants_rec.nj,
:participants_rec.nb_buts,
:participants_rec.carton_jaune,
:participants_rec.carton_rouge;
End Loop;
Close c_rec;
--- Fin du Code à ajouter au déclencheur
--
END IF;
--- End EQUIPES detail program section
---- Begin EQUIPES1 detail program section
-IF ( (:MATCHS.NE_DEPLACANTE is not null) ) THEN
rel_id := Find_Relation('MATCHS.MATCHS_EQUIPES1');
Query_Master_Details(rel_id, 'EQUIPES1');
--- Début du Code à ajouter au déclencheur pour afficher PATCICIPANTS1
--
Go_Block ('PARTICIPANTS1');
Clear_Block;
First_Record;
Open c_dep;
-- message('ne = '||:matchs.ne_recevante);
-- message('nm = '||:matchs.nm);
Fetch c_dep into
:participants1.nj,
:participants_dep.nb_buts,
:participants_dep.carton_jaune,
:participants_dep.carton_rouge;
While c_dep%found Loop
Next_Record;
Fetch c_dep into
:participants_dep.nj,
:participants_dep.nb_buts,
:participants_dep.carton_jaune,
:participants_dep.carton_rouge;
End Loop;
Close c_dep;
--- Fin du Code à ajouter au dévlencheur
--
END IF;
--- End EQUIPES1 detail program section
-IF ( :System.cursor_item <> startitm ) THEN
Go_Item(startitm);
Check_Package_Failure;
END IF;
END;
--- End default relation program section
--
II Ajout d'éléments calculés
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
30
Modifier le module pour que :
1. le module présente les noms des joueurs comme sur la figure 2,
2. on puisse inscrire de nouveaux joueurs dans chacune des 2 équipes, en utilisant une LOV sur
chaque bouton "inscrire".
On modifiera la propriété Visible des éléments à masquer et on ajoutera le code suivant à un
déclencheur POST-QUERY attaché aux 2 blocs PARTICIPANTS_DEP et PARTICIPANTS_REC
-- pour le bloc PARTICIPANTS_DEP
select nom
into :participants_dep.nomj
-– "nomj" présente les noms des joueurs
from joueurs
where :participants_dep.nj=nj;
Figure 2 : formulaire permettant de saisir "intelligemment" les participants d'un match
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
31
P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue
32
Téléchargement