TRIGGER
Un trigger est associé à une table ou vue et permet d'exécuter du code selon un évènement donné. Tout comme les procédures stockées, tout s'exécute sur le serveur. Le trigger n'est jamais appelé directement. C'est lorsque l'évènement auquel est associé le trigger survient, le code est alors exécuté. Le langage utilisé par la base de données peut être utilisé pour le trigger, point besoin d'être limité à du SQL. Il est donc possible d'effectuer des tâches très complexes très aisément en utilisant ce langage au lieu d'avoir à gérer de complexe et lourde requête SQL.Il est donc possible de se passer des triggers, mais un plus grand effort sera nécessaire pour parvenir au même objectif. Un trigger est exécuté sur le serveur, il n'y a donc pas de trafic réseau qui est généré telle que lors de requête SQL. Cette centralisation permet que plusieurs applications puissent y avoir accès. Si un changement doit se faire, il n'est pas nécessaire de recompiler l'application. L'utilisation de cette technique peut alors s'avérer beaucoup plus rapide que son équivalent en SQL. Un trigger n'a aucun paramètre d'entré et de sortie.
Il est possible d'utiliser les triggers pour diverses raisons:
- Gérer l'intégrité des données
- Gérer les règles d'affaires
- Sécurité
- ...
Syntaxe d'un trigger
CREATE TRIGGER name FOR { table | view} [ACTIVE | INACTIVE] {BEFORE | AFTER} {DELETE | INSERT | UPDATE} [POSITION number] AS < trigger_body > < trigger_body > = [< variable_declaration_list >] < block > < variable_declaration_list > =DECLARE VARIABLE variable < datatype >; [DECLARE VARIABLE variable < datatype > ;...] < block > = BEGIN < compound_statement > [< compound_statement >...] END < compound_statement > = {< block > | statement;}
Il existe tel qu'on peut le voir certaines ressemblances avec la syntaxe des procédures stockées
Opérateur
Les conditions et les boucles sont identiques à celles qu'on a pu voir dans les procédures stockéesUn trigger peut être exécuté pour les évènements suivants
- BeforeInsert
- BeforeUpdate
- BeforeDelete
- AfterInsert
- AfterUpdate
- AfterDelete
SET TERM ^; CREATE TRIGGER TRIG_CLIENT_GenId FOR CLIENT ACTIVE BEFORE INSERT AS BEGIN IF ( NEW.NOCLIENT IS NULL ) THEN NEW.NOCLIENT = GEN_ID(TRIG_CLIENT_GenId,1); END
Ce trigger permet automatiquement de renseigner la clé primaire de la table. Il n'est alors plus nécessaire d'intervenir, Interbase le fait pour nous. Une telle approche permet d'éviter les erreurs en cas d'omission.
Création d'une table
create table tclient( noms char(12), prenom char(12), motpasse char(12) );
SET TERM ^; CREATE TRIGGER TRIG_CLIENT_GenId FOR CLIENT ACTIVE AFTER INSERT AS BEGIN IF ( NEW.motpasse IS NULL ) THEN NEW.motpasse = 'tmp'; END
La création de cette table ainsi que la procédure stockée permet de mettre un mot de passe si aucun n'a été inclus.Il est possible de faire appel à une procédure stockée ou un UDF dans un trigger
UDF
UDF signifie fonction définie par l'usager (user defined function). Ces UDF sont bien entendu exécutés sur le serveur, la majorité du temps, le langage utilisé est le c ou le c++. Il est possible d'utiliser d'autre langage. Dans les répertoires d'Interbase, il y a de nombreux exemples.Les UDF sont utilisés pour ajouter des fonctionnalités non disponibles dans SQL.
Les UDF ont 2 défauts: lorsqu'une UDF est exécuté, aucun accès à la BD ne peut survenir (affecte interbase inférieur à 7). Le second est que si le besoin de changer de machine pour une quelques raisons, on doit installer tous les UDF avant de restaurer la sauvegarde de la bd.
Lorsqu'on créer une UDF, on doit garder à l'esprit qu'elle devrait être le plus simple possible. Il est tout à faire possible dans une UDF d'exécuter un programme ou de faire des insertions, suppression... mais une telle approche peut mettre diminuer significativement les performances du serveur de plus ça pourraient occasionner une congestion des transactions.
Interbase inclus plusieurs UDF dont:
- lower: converti une chaîne de caractère en minuscule
- strcat: concatène deux chaînes
- substr: retourne une portion d'une chaîne
- trim: enlève les espaces d'une chaîne
- trunc: trunc une chaîne
- sysdate: retourne la date du système
- sqrt: retourne la racine carré d'un double
- abs : retourne la valeur absolue d'un double
Création d'une UDF avec delphi
Nous allons créer une UDF qui retournera la taxe (7%) sur un chiffre passé en paramètre- Choisir l'expert dll
- Ajouter une unité au projet
- Sauvegarder l'unité sous le nom MathFct
- Sauvegarder le projet sous le nom brudflib
unit MathFct; interface function TaxeTps(var i:Double): Double; cdecl; export; implementation function TaxeTps(var i:Double): Double; cdecl; export; begin result := i*0.07+i; end; end.
Voici maintenant le code du projet
library brudflib; uses SysUtils, Classes, MathFct in 'MathFct.pas'; {$R *.res} exports TaxeTps; begin end.
Notez la présence du exports. TaxeTps fait partie de cette section, elle pourra donc être utilisé par un autre programme. Il aurait été possible dans l'unité MathFct d'avoir plusieurs fonctions, mais que seulement quelque unes soit accessible de l'extérieur.Ne pas oublier que tous les paramètres dans une UDF sont passés par pointeur donc il ne faut pas oublier de mettre var devant nos paramètres.
En exécutant le projet, une dll est créé brudflib.dll. Cette dll doit être placée dans le répertoire UDF d'Interbase, habituellement c'est: disqu:\Borland\InterBase\UDF\. Il faut par la suite déclarer cette fonction pour l'utiliser dans Interbase.
Syntaxe de la déclaration de l'UDF pour Interbase
Voici la syntaxe d'une UDF:DEFINE EXTERNAL FUNCTION name [<datatype> | CSTRING (int) [, <datatype> | CSTRING (int) ...]] RETURNS {<datatype> [BY VALUE] | CSTRING (int)} ENTRY_POINT "<entryname>" MODULE_NAME "<modulename>" ;
Déclarons maintenant la fonction à Interbase
Declare external function f_TaxeTps float returns float by value entry_point 'TaxeTps' module_name 'brudflib.dll';
Il est maintenant possible d'utiliser cette fonction dans Interbase. Nous pouvons donc effectuer ce genre de requête:
select f_TaxeTps(12.5) from rdb$database
L'exécution de cette requête retournera bien attendu 13,375. Les fonctions ainsi créées peuvent être ensuite utilisées dans n'importe quelle requête. Imaginons que nous avons une table logicielle avec un champ prix. Nous pourrions connaitre le coût du logiciel après taxe en faisant: select f_TaxeTps(prix) from logiciel.
String
Jusqu'à maintenant, nous avons utilisé que des nombres, nous allons maintenant utilisé des chaînes de caractères. Les strings utilisés par Delphi, lui sont propres. Interbase ne les utilise pas. Nous allons donc être obligés d'utiliser la fonction PChar.function MixStr(Incoming: PChar):PChar;cdecl; export; var OutStr, IncomingStr: string; i, j: Integer; begin IncomingStr := StrPas(Incoming); OutStr := ''; while Length(IncomingStr) > 0 do begin i := Random(Length(IncomingStr) - 1) + 1; OutStr := OutStr + IncomingStr[i]; Delete(IncomingStr, i, 1); end; StrPCopy(Incoming, OutStr); result := Incoming; end;
Tappez ce code sous votre outil de gestion de bd:
Declare external function f_MixStr cstring(64) returns cstring(64) entry_point 'MixStr' module_name 'brudflib2.dll'; select f_MixStr('linux') from rdb$databaseVous devriez voir que les lettres du mot Linux ont changé de position.
Suppression
Il suffit de taper drop external function nom_de_la_fonction pour la supprimer de la bd. Pour notre fonction, ça serait:drop external function f_MixStr;