oracle complet siad

Post on 28-Dec-2015

35 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

DESS IGSI Formation continue INGENIERIE ET GESTION DES SYSTEMES D'INFORMATION

P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation continue

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 2

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 3

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 4

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 5

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 6

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_partici per 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 7

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 8

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 9

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 10

Figure 3 : formulaire avec un bloc maître et un bloc détail Figure 4 : Création de la relation entre 2 blocs

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 11

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 12

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 13

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 14

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 15

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 uti lisateurs 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 16

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. Certaines comportent des inconvénients.

Solution 1 :

Création d’un déclencheur WHEN-MOUSE-DOUBLECLICK pour l’item NJ avec le code ci-dessous. 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'); /* LOV_NJ est le no m de la LOV */ END;

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_statu s; rep boolean; BEGIN IF ( recstat <> 'NEW' and recstat <> 'INSERT' ) T HEN RETURN; END IF; rep:=show_lov('LOV_NJ'); END;

P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue 17

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 18

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 19

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 ('NOM_DU_BLOC', DEFAULT_WHERE, 'prédicat');

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 20

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 21

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 F orm*/ --raise form_trigger_failure; /* ne marche pas dan s 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 22

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 23

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_JOUEUR S'); 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 24

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_W HERE, 'NM = '||:restriction.nm); Go_Block ('PARTICIPANTS'); Execute_Query; end if; end;

Le code du déclencheur WHEN-BUTTON-PRESSED associé au bouton "TOUT_AFFICHER" est donné ci-dessous :

begin SET_BLOCK_PROPERTY ('PARTICIPANTS', DEFAULT_WHER E''); 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 := Show_Alert ('NOM_DE_L_ALERTE'); /* rep onse est de type numerique */

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 25

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 number (11); V_nbj number; reponse 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 count(nj) into V_nbj from joueurs where 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 26

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 nb_buts Into old_nb_buts From participants Where nj = :participants.nj and nm = :participan ts.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 27

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 28

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-POPULATE-DETAILS 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_EQUIP E_DEP' -- -- Begin EQUIPES_REC detail program section -- IF ( (:MATCHS.NE_RECEVANTE is not null) ) THEN rel_id := Find_Relation('MATCHS.MATCHS_EQUIPE_R EC'); Query_Master_Details(rel_id, 'EQUIPE_REC'); -- -- Début du Code à ajouter au déclencheur -- Set_Block_Property('PARTICIPANTS_REC',DEFAULT_W HERE,

'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_D EP'); Query_Master_Details(rel_id, 'EQUIPE_DEP'); -- -- Début du Code à ajouter au déclencheur -- Set_Block_Property('PARTICIPANTS_DEP',DEFAULT_W HERE,

'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 29

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_r ouge 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_r ouge 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 30

: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 31

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 l es noms des joueurs from joueurs where :participants_dep.nj=nj;

Figure 2 : formulaire permettant de saisir "intelli gemment" les participants d'un match

P.-J. Charrel & J.-M. Thévenin, Université Toulouse 1, DESS IGSI Formation Continue 32

top related