Chapitre Interfaces de Programmation 1. TRIGGER

Transcription

Chapitre Interfaces de Programmation 1. TRIGGER
BASE DE DONNEES – 2d Cycle
Chapitre
Interfaces de Programmation
1. TRIGGER
1.1. Définition du ‘trigger’ = ‘reflexe’ = ‘déclencheur’
C’est une procédure cataloguée dans la base de données, dont l’exécution est déclenchée par l’occurrence
de l’événement associé au trigger.
Cet événement survient à la suite de conditions particulières :
- opération de mise à jour d’une table, d’un tuple
- passage à vrai d’une condition sur une ou plusieurs valeurs de données
- combinaison d’une occurrence d’opération de mise à jour et d’une condition sur valeur de données
Le trigger est un moyen de prendre en compte dans le SGBDR, des contraintes sémantiques complexes
que la clause CHECK ne permet pas de déclarer.
1.2. Création de triggers dans la norme SQL
(normalisation prévue dans SQL3)
CREATE TRIGGER trigger_name
AFTER | BEFORE
INSERT | UPDATE | DELETE [ OR INSERT | UPDATE | DELETE …]
ON relation_name
WHEN condition
Action-procedure
[FOR EACH ROW | STATEMENT ]
Exemple de création d’un trigger, sous Oracle, qui ajoute un tuple dans la table ‘commande_en_attente’,
quand la quantité en stock d’un article devient inférieure à la quantité minimale spécifiée pour cet article :
CREATE TRIGGER tg_reapprovision
AFTER UPDATE ON article
FOR EACH ROW
WHEN article.qte_stock < article.qte_min
DECLARE x number
BEGIN
SELECT count(*) INTO x
FROM commande_en_attente C WHERE C.num_art = article.num_art ;
IF (x = 0)
THEN INSERT INTO commande_en_attente
VALUES(article.num_art, article.qte_reapprov, SysDate);
ENDIF;
END;
1.3. Création de triggers dans Postgresql
CREATE TRIGGER trigger_name
AFTER | BEFORE
INSERT | UPDATE | DELETE [ OR INSERT | UPDATE | DELETE …]
ON relation_name
[FOR EACH ROW | STATEMENT ]
EXECUTE PROCEDURE function();
où
trigger_name = nom du trigger ; relation_name = nom de la relation à laquelle s’applique l’événement
function = fonction de trigger sous la forme d’une procédure stockée, exécutée quand survient
l‘évènement
1/6
BASE DE DONNEES – 2d Cycle
Note1 : PostgreSql ne permet pas l’exécution d’un trigger sur occurrence d’une condition mais
uniquement AVANT ou APRES une commande (ou instruction = statement) de type Insert,
Update ou Delete.
Note2 : La fonction de trigger doit être créée avant le trigger. Elle doit être définie comme une fonction
sans arguments retournant le type TRIGGER.
Note3 : La fonction peut être exécutée pour chacun des tuples concernés par la commande (For each
row) ou une seule fois pour la commande (For each statement).
Pour l’instant PostgreSql n’implémente le trigger qu’au niveau tuple (For each row).
Note4 : Pour l’instant, PostgreSql ne permet pas d’ouvrir et de fermer une transaction dans une
procédure stockée.
Les ordres BEGIN TRANSACTION et END TRANSACTION doivent être spécifiés avant et
après l’appel de la procédure stockée.
Un exemple de trigger sous PostgreSql :
Dans le schéma relationnel d’une école de conduite, lors d’un changement de véhicule pour un élève, on souhaite
conserver dans une table archive trace de ce véhicule et du véhicule qui le remplace.
Eleve(numel, nomel, preel, adrel, cpel, fixel, mobel, immat#)
Arch_eleve (numel, immat, datchange, immat_de_rempl)
La fonction à créer pour le trigger est la suivante :
CREATE FUNCTION archive_eleve () RETURNS TRIGGER AS '
BEGIN
IF NEW.immat != OLD.immat THEN
INSERT INTO arch_eleve
Values (OLD.numel, OLD.immat,’today’,NEW.immat);
END IF;
RETURN NEW;
END;
' LANGUAGE 'plpgsql';
Le trigger à créer est le suivant :
CREATE TRIGGER trg_ach_elev BEFORE UPDATE ON eleve
FOR EACH ROW EXECUTE PROCEDURE archive_eleve () ;
1.4. Exécution des triggers
Le code de la procédure stockée du trigger est automatiquement exécuté par le SGBDR au moment et
selon la condition spécifiés dans l'ordre de création du trigger :
- avant la finalisation de l'opération si "BEFORE UPDATE|DELETE|INSERT"
- après la finalisation de l'opération si "AFTER UPDATE|DELETE|INSERT"
- avant la finalisation de l'opération si "BEFORE UPDATE|DELETE|INSERT" et sur occurrence de la
condition spécifiée
- après la finalisation de l'opération si "AFTER UPDATE|DELETE|INSERT" et sur occurrence de la
condition spécifiée
Exemple du trigger Oracle ci-dessus
sachant que la quantité minimum requise pour l'article concerné est de 50,
la commande suivante
Update article set qte_stock = qte_stock + 100 where num_art = 12030;
ne déclenchera pas l'exécution de la séquence de code du trigger
alors que, avec un stock avant update de 100, la commande suivante
Update article set qte_stock = qte_stock - 70 where num_art = 12030;
déclenchera l'exécution de la séquence de code du trigger
Exemple du trigger Postgresql ci-dessus
les commandes suivantes
2/6
BASE DE DONNEES – 2d Cycle
Insert into Eleve values(12030,'TARTAN','Pierre','5 rue des
As','97110','0590000000','069000000','123WWW971');
Delete from Eleve where numel = 11111;
ne déclencheront pas l'exécution de la fonction de trigger
alors que, les commandes suivantes
Update Eleve set cpel = '97139' where numel = 12030;
Update Eleve set immat = '97ZZZ971' where numel = 12030;
déclencheront l'exécution de la fonction de trigger
2. Langage procédural PL/SQL
Le langage PL/SQL est un langage procédural comportant des instructions structurées (condition,
boucles) en plus des instructions SQL.
Disponible dans tous les SGBDR, il prend le nom de PL/pgSQL sous PostgreSql (PL/SQL sous Oracle).
Un programme en PL/pgSQL est organisé en blocs de code créés dans la base par un ordre CREATE
FUNCTION. Chaque bloc peut contenir une infinité de sous-blocs. Chaque sous-bloc doit respecter la
structure de bloc , i.e. commencer par DECLARE (optionnel), suivi de BEGIN , et se terminer après les
instructions par un END.
CREATE FUNCTION identifier (arguments) RETURNS type AS
'
DECLARE
declaration;
[...]
BEGIN
statement;
[...]
END;
'
LANGUAGE 'plpgsql';
Commentaires PL/PGSQL
Ligne simple de commentaires :
-- ceci est un commentaire
Bloc de commentaires :
/* ceci est
un bloc de
commentaires
*/
Arguments des fonctions PL/pgSQL
La liste d’arguments spécifie uniquement le type de chaque argument.
Chaque argument est affecté d’un identifiant de la forme $i où i est le numéro de l’argument ($1
pour le 1er, $2 pour le second, …etc)
Une variable peut être associé à un argument en utilisant ALIAS FOR dans la partie déclarative de la
fonction :
Identifiant_de_variable ALIAS FOR $i
Variables PL/PGSQL
Les variables doivent toutes être déclarées dans le sous-bloc DECLARE.
nom_de variable [CONSTANT] type_de_donnée [NOT NULL]
3/6
[ [DEFAULT] := value ] ;
BASE DE DONNEES – 2d Cycle
Exemples :
Paiement char := ‘’O’’;
Nb_comm integer ;
C_number CONSTANT integer := 100 ;
Les variables non initialisées reçoivent la valeur NULL par défaut
Les types simples sont les types standards SQL : boolean, text, char, varchar,
time
Ces types sont complétés par le type Record.
integer, float, date,
Variables PL/PGSQL prédéfinies
FOUND : variable booléenne affectée par un ‘Select into’, peut être immédiatement testée après cette
commande pour savoir si le select a retourné un résultat
Variables PL/PGSQL prédéfinies spécifiques aux fonctions de TRIGGERS
Nom
Type
Description
Nouveau
tuple créé après un ordre Insert ou Update
NEW
Record
OLD
Record Ancien tuple laissé par un ordre Delete ou Update
Nom du trigger déclenché
TG_NAME
Name
‘BEFORE’ ou ‘AFTER’ selon la spécification du trigger
TG_WHEN
Text
‘ROW’ ou ‘STATEMENT’ selon la spécification du trigger
TG_LEVEL
Text
‘INSERT’ ou ‘UPDATE’ ou ‘DELETE’ selon l’opération qui a déclenché le
TG_OP
Text
TG_RELID
Oid
TG_RELNAME Name
trigger
Identification (ID) de l’objet (relation) auquel est associé le trigger
Nom de la relation à laquelle est associé le trigger
Variables ‘attribut’
Une variable est déclarée avec ‘attribut’ quand elle destinée à contenir les valeurs d’un objet de la base ;
il n’est pas nécessaire de connaître le type de cet objet, le type de la variable y sera automatiquement
adapté.
Les attributs sont au nombre de 2 :
- attribut %TYPE. La déclaration est la suivante :
nom_de_variable nom_de_table . nom_de_colonne%TYPE
permet de définir une variable correspondant à un attribut d’une relation
- attribut %ROWTYPE. La déclaration est la suivante :
nom_de_variable nom_de_table%ROWTYPE
permet de définir une variable correspondant à un tuple d’une relation
Exemples :
Un_client Client%ROWTYPE ;
Nom_client Client.nomcl% TYPE;
Instructions PL/PGSQL
Affectation
Variable := expression
Où expression = constante | variable | expression arithmétique(variable, constante) |
expression logique(variable, constante)
Select into Variable Attribut from relation [ where …..] ;
la variable reçoit la valeur de l’attribut projeté
Select into V1, V2, ,Vn A1,A2, ,An from relation [ where …..] ;
les variables V1,V2, ,Vn reçoivent les valeurs des attributs projetés A1,A2, ,An
4/6
BASE DE DONNEES – 2d Cycle
NOTE : En PL/pgSQL, pour avoir l’équivalent de la commande SQL ‘Select into’ qui crée une
nouvelle table, utiliser ‘Create table as select …‘
Return
Return {variable | expression(variable, constante) }
Instruction qui retourne une valeur du type spécifié dans la déclaration de la fonction
Une instruction ‘Return’ doit toujours être incluse avant le ‘END’ de la fonction (même si elle n’est
jamais exécutée)
IF … THEN
IF condition THEN instruction; [ .....]
END IF;
IF … THEN … ELSE
IF condition THEN instruction; [ .....]
ELSE instruction; [ .....]
END IF;
Imbrications de IF … THEN … ELSE
Boucle inconditionnelle
LOOP instruction [ .....] EXIT [étiquette] [WHEN condition ] END LOOP;
Cette instruction boucle jusqu’à rencontrer l’instruction ‘EXIT’. Cette dernière peut être
conditionnée par ‘WHEN’ qui précise quand la sortie de boucle doit s’effectuer.
Boucle WHILE
WHILE condition LOOP instruction [ .....]
END LOOP;
Similaire à la boucle ‘while’ dans les langages de programmation standard (Pascal, C,….)
Boucle FOR
FOR identifiant IN expression1 . . expression2 LOOP instruction [ .....]
END LOOP;
identifiant est une variable de type entier créée automatiquement en début de boucle puis
détruite à la fin. Il n’est pas nécessaire de la déclarer explicitement (sous DECLARE).
expression1 et expression2 sont des expressions entières.
ou
FOR variable IN instruction_SELECT LOOP instruction [ .....]
END LOOP;
variable est une variable déclarée de type RECORD ou avec l’attribut ROWTYPE
Un exemple de fonction :
Dans la base de données d’une école de conduite, on crée une fonction qui pour un numéro d’élève donné retourne une
chaîne de caractère concaténant le nom et le prénom de l’élève modélisé par la relation :
Eleve(numel, nomel, preel, adrel, cpel, fixel, mobel, immat#)
La fonction est la suivante :
CREATE FUNCTION ident_eleve (int4) RETURNS varchar(100) AS '
DECLARE
Num_elev ALIAS FOR $1;
Nom_elev eleve.nomel%TYPE;
Pren_elev eleve.preel%TYPE;
Ident varchar(100);
BEGIN
SELECT INTO Nom_elev, Pren_elev
Nomel, preel
FROM eleve
WHERE numel = Num_elev;
IF FOUND THEN
Ident := Nom_elev || Pren_elev;
5/6
BASE DE DONNEES – 2d Cycle
ELSE
Ident := “Numero Eleve INEXISTANT”
END IF;
RETURN Ident;
END;
' LANGUAGE 'plpgsql';
Utilisation de PL/PGSQL dans une base de données
Définir le langage PL/pgSQL comme objet de la base de données
Pour pouvoir être utilisé dans une base de données, le langage PL/PGSQL doit préalablement être défini
par l’administrateur de la base comme un objet de la base de données.
Deux méthodes pour cela :
1) sous ‘psql’, avec des ordres SQL :
- d'abord créer dans la base le gestionnaire des appels procéduraux (procedural call Handler)
Create Function plpgsql_call_handler ()
Returns OPAQUE
As ‘/var/lib/pgsql/plpgsql.so’
Language ‘C’
;
où /var/lib/pgsql est le chemin du répertoire contenant la bibliothèque de PostgreSql ;
dans certaines configuration il s’agit du répertoire /usr/ /lib/pgsql
- ensuite créer l’objet language
Create Language ‘plpgsql’
Handler plpgsql_call_handler
Lancompiler ‘PL/Pgsql’
;
2) sur la ligne de commande système, avec l’utilitaire :
createlang plpgsql nom_base_de_données
Créer une fonction stockée :
Par la commande Create Function (Cf. ci-dessus)
Appel d’une fonction stockée :
Select nom_de_fonction (arguments) ;
ou
nom_de_variable := nom_de_fonction (arguments)
ou
PERFORM nom_de_fonction (arguments)
6/6