~~SLIDESHOW~~ ====== Gestion des données – La programmation au sein d’un SGBD - les déclencheurs (triggers) ====== Notions abordées : * Le respect de contraintes d’intégrité avancées à l’aide de déclencheurs ; * La conception de déclencheurs, alias triggers ; ===== Rappels : Contraintes d’intégrité ===== Une contrainte d'intégrité est une règle qui définit la cohérence d'une donnée ou d'un ensemble de données de la BD. Les contraintes d’intégrité sont des règles que les attributs des relations doivent respecter afin d’assurer le bon fonctionnement du modèle. Il existe deux types de contraintes : * sur une colonne unique, * ou sur une table lorsque la contrainte porte sur une ou plusieurs colonnes. Les contraintes sont définies au moment de la création des tables. ===== ===== Les contraintes d'intégrité sur une colonne sont : * PRIMARY KEY : définit l'attribut comme la clé primaire * UNIQUE : interdit que deux tuples de la relation aient la même valeur pour l'attribut. * REFERENCES () : contrôle l'intégrité référentielle entre l'attribut et les colonnes spécifiées d'une autre table * CHECK () : contrôle la validité de la valeur de l'attribut spécifié dans la condition dans le cadre d'une restriction de domaine ===== ===== Les contraintes d'intégrité sur une table sont : ===== ===== Les différentes contraintes d’intégrité : * La contrainte de domaine * La contrainte de relation * La contrainte de référence ou contrainte d’intégrité référentielle ===== Contraintes d'intégrité avancé : les limites de SQL ===== Le langage SQL usuel permet de nombreuses opérations sur les bases de données mais ne suffit malgré tout pas à implémenter toutes les règles de gestion inhérentes à celles-ci. En effet, il est par exemple impossible d’assurer l’intégrité des données dès lors que le modèle de données nécessite la mise en œuvre de **contraintes d’intégrité avancées.** ===== ===== En particulier, les **contraintes d’entités (l’héritage)** ou encore les **contraintes d’associations (inclusion, exclusion, etc.)** ne peuvent être mises en œuvre au moyen de simples clefs étrangères ou encore de contraintes de domaine (CHECK). Pareillement, **l’historisation ou encore la stabilité constituent des contraintes tout à fait modélisables en Merise 2 mais dont la mise en œuvre s’avère inenvisageable avec du SQL habituel**. On ne pourra pas non plus envisager la mise en place de **champs calculés**, pourtant si pratiques aux fins d’optimiser les requêtes statistiques en outre. ===== ===== Ainsi le langage SQL a-t ’il fait l’objet d’enrichissements successifs de sorte que de nouvelles notions sont apparues de manière à pouvoir solutionner des problématiques telles que celles évoquées ci-avants. Ces notions font même désormais partie de la norme SQL : **trigger, événements, procédures et fonctions stockées. ** C’est dans ce contexte que l’on étudie ci-après la notion de triggers. Procédures et fonctions stockées feront l’objet d’un cours venant compléter celui-ci. ===== Les déclencheurs (triggers) ===== Un trigger est une règle spécifiant une action à exécuter sur la BD, quand une condition est vérifiée, suite à une mise à jour ou une interrogation. C'est un algorithme exécuté à l’occasion d’un événement se produisant sur une table d’une base de données. Ce mécanisme est aussi nommé déclencheur. Un trigger est de la forme : ===== ===== * sur <événement> * si * alors __Exemple__ * sur MAJ de la relation PRODUIT * si PRODUIT.QTE < SEUIL * alors passer une commande du produit ===== ===== ==== les <événements> ==== Les événements sont typiquement les suivants : * BEFORE INSERT : pour exécuter un trigger avant l’insertion d’une nouvelle ligne au sein d’une table. La nouvelle ligne n’est donc pas encore dans la table au moment de l’exécution du trigger. * AFTER INSERT : pour exécuter un trigger après l’insertion d’une nouvelle ligne au sein d’une table. La nouvelle ligne existe donc effectivement dans la table au moment de l’exécution du trigger. ===== ===== * BEFORE UPDATE : pour exécuter un trigger avant la modification d’une ligne existant dans une table. L’ancienne ligne n’a pas encore été affectée par la modification au moment où le trigger est exécuté. * AFTER UPDATE : pour exécuter un trigger après la modification d’une ligne qui existait dans une table. L’ancienne ligne a par conséquent déjà été affectée par la modification au moment où le trigger est exécuté. ===== ===== * BEFORE DELETE : pour exécuter un trigger avant la suppression d’une ligne. L’ancienne ligne existe par conséquent encore au moment où le trigger est exécuté. * AFTER DELETE : pour exécuter un trigger après la suppression d’une ligne. L’ancienne ligne n’existe par conséquent plus au moment où le trigger est exécuté. ===== ===== Un trigger peut, au besoin être attaché à plusieurs événements (exemple : BEFORE INSERT, UPDATE). Quoiqu’il en soit, un déclencheur est un réel **algorithme**. En cela, dès lors que l’on s’attaque à l’implémentation de trigger, le SQL devient un réel **langage de programmation**. ===== ===== ==== la notion de transaction (=sécurisation des traitements) ==== L’exécution d’un trigger est encapsulée dans ce qu’on appelle une transaction. Une transaction, c’est un ensemble de traitements qui doivent s’exécuter en bloc. Si l’un des traitements échoue, toute la transaction échoue et tous les traitements qui ont été exécutés sont annulés. L’on peut valider une transaction. C’est ce qu’on appelle un COMMIT. Au contraire, l’on peut faire échouer une transaction. C’est ce qu’on qualifie de ROLLBACK. ===== ===== En MySQL, conformément à la norme, on fait échouer une transaction en levant une erreur grâce à l’instruction SIGNAL. __Exemple :__ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'An error occurred', MYSQL_ERRNO = 1001; Quel est l’intérêt de faire échouer une transaction ? Très simplement, la logique veut que, lors de l’exécution d’une requête, si une contrainte d’intégrité n’est pas vérifiée, la transaction en question échoue. ===== ===== ==== les mots clés NEW et OLD ==== Que représente l’opérateur NEW ? * Dans le code d’un trigger, le mot-clef NEW permet d’utiliser la ligne en cours d’insertion ou de modification. Syntaxe : NEW.nomChamp . Que représente l’opérateur OLD ? * Dans le code d’un trigger, le mot-clef OLD permet d’utiliser la ligne qui a été ou va être modifiée ou supprimée. Syntaxe : OLD.nomChamp . ===== ===== __**Quand peut-on les utiliser ?**__ ^Evénement (BEFORE ou AFTER) ^NEW ^OLD ^ |INSERT|OUI |NON | |UPDATE |OUI |OUI | |DELETE |NON |OUI | ===== ===== __Explication : __ * À l’insertion, l’on insère une nouvelle ligne. Il n’y a pas d’ancienne ligne (OLD) mais bien une nouvelle (NEW). De ce fait, l’opérateur OLD est inutilisable. * À la mise à jour, l’on vient modifier une ligne préexistante. Il y a donc une ancienne ligne (OLD) et une nouvelle (NEW), à savoir la même mais modifiée. NEW et OLD sont dès lors utilisables. * À la suppression, l’on souhaite retirer une ligne préexistante. Il n’est pas question de nouvelle ligne (NEW) mais l’ancienne va être ou a été supprimée (OLD). On peut par conséquent utiliser OLD mais on ne peut utiliser NEW. ===== ===== ==== L’intérêt ==== Si nous pouvons exécuter un programme lorsqu’un événement se produit, nous pouvons désormais, entre autres choses, vérifier des contraintes d’intégrité avancées. Et c’est ce que nous allons tâcher de montrer au travers de quelques exemples. [[Exercices d'applications]] ===== Pour conclure ===== En pratique, la logique métier d’un logiciel implique en général la conception ou l’évolution d’une base de données dont l’intégrité ne peut être assurée qu’au prix de nombreux contrôles. Il importe d’être capable d’identifier les contrôles à mettre en œuvre et d’établir les algorithmes nécessaires à leur mise en œuvre, qu’il s’agisse de les concevoir sous forme applicative ou sous forme de triggers. ===== Avantages ===== Les triggers permettent de mettre en œuvre des contrôles d’intégrité avancées. A l’inverse des contrôles applicatifs, lesquels nécessitent des va-et-vient entre le logiciel et le SGBD, les triggers permettent un accès direct à la base de données, ce qui améliore donc le temps de réponse de vos applications et sécurise l’accès aux données. Plus encore, l’exécution du code d’un trigger étant réalisée au sein même du SGBD, l’algorithme développé peut profiter des optimisations effectuées par le SGBD (tables d’index, fonctions de calcul optimisées, etc.). ===== ===== Cela permet également de partager la source de données entre plusieurs applications sans rompre la logique de validation, d’intégrité de la base de données. Comme le serveur de base de données exécute des triggers, ils peuvent profiter de ressources serveur améliorées telles que la RAM et le processeur. En somme, l’avantage du recours aux triggers réside avant tout dans les performances qu’ils peuvent procurer. ===== Inconvénients ===== Quoique des normes SQL existent et que les implémentations du langage SQL tendent à s’harmoniser ces dernières années, la syntaxe utilisée demeure relativement propre au SGBDR utilisé. Par exemple, SQL Server dispose de sa propre implémentation, appelée Transact-SQL et souvent abrégée TSQL. De même, Oracle dispose d’une implémentation appelée PL-SQL. Ainsi, la première limite des triggers réside dans le fait que le SQL avancé, celui que nous étudions dans ce cours, ne soit pas interopérable. De plus, la syntaxe SQL employée peut sembler relativement lourde en comparaison de celles des langages les plus courants (PHP, Python, Java, etc.). Finalement, ces derniers langages offrent une syntaxe souvent plus étoffée que celle du SQL. ===== Alternative ===== Un trigger n’est finalement qu’un simple programme. Et il est très fréquent de vérifier les contraintes d’intégrité de façon logicielle. On parle de contrôle logiciel ou de contrôle applicatif. Autrement dit, c’est souvent le logiciel ou les logiciels interagissant avec une base de données qui procèderont à la vérification des règles de gestion et des contraintes d’intégrité en particulier. On considérera communément que ces vérifications font partie de la logique métier. ===== ===== Ce choix offre souvent l’avantage de la portabilité, de l’interopérabilité. Effectivement, une migration de base de données ou une duplication de la base de données vers un autre SGBD sera sans effet sur la vérification des contraintes. De surcroît, les langages de programmations actuels disposent en général d’une syntaxe plus aboutie et plus facile d’utilisation que celle proposée par la norme SQL. Plus encore, ces derniers sont souvent accompagnés de frameworks de type ORM (Object Relational Mapping) permettant de vérifier de manière élégante des contraintes d’intégrités avancées.