La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Créer des déclencheurs de base de données

Présentations similaires


Présentation au sujet: "Créer des déclencheurs de base de données"— Transcription de la présentation:

1 Créer des déclencheurs de base de données

2 Objectifs A la fin de ce chapitre, vous pourrez :
décrire différents types de déclencheur décrire les déclencheurs de base de données et leur utilisation créer des déclencheurs de base de données décrire les règles d'activation des déclencheurs de base de données supprimer des déclencheurs de base de données But du chapitre Dans ce chapitre, vous allez apprendre à créer et à utiliser des déclencheurs (triggers) de base de données.

3 Types de déclencheur Un déclencheur :
est une procédure ou un bloc PL/SQL associé à la base de données, à une table, à une vue ou à un schéma s'exécute de façon implicite lorsqu'un événement donné se produit il peut s'agir d'un : déclencheur applicatif, qui s'exécute lorsqu'un événement se produit dans une application donnée déclencheur de base de données, qui s'exécute lorsqu'un événement de type données (LMD) ou système (connexion ou arrêt) se produit dans un schéma ou une base de données Types de déclencheur Les déclencheurs applicatifs s'exécutent implicitement lorsqu'un événement LMD (Langage de manipulation de données) déterminé se produit au sein d'une application. Par exemple, une application développée via Oracle Forms Developer utilise de nombreux déclencheurs. Les déclencheurs de base de données s'exécutent implicitement lorsque se produit un événement portant sur les données tel que l'exécution d'une instruction LMD sur une table (une instruction de déclenchement INSERT, UPDATE ou DELETE), le lancement d'un déclencheur INSTEAD OF sur une vue ou l'exécution d'instructions LDD (CREATE et ALTER), quel que soit l'utilisateur connecté ou l'application utilisée. Ils s'exécutent de manière implicite lorsque certaines actions utilisateur ou système se produisent (connexion d'un utilisateur ou fermeture de la base de données par l'administrateur, par exemple). Remarque : Les déclencheurs de base de données peuvent être définis sur des tables et des vues. Si une opération LMD est exécutée sur une vue, le déclencheur INSTEAD OF définit les actions qui doivent se produire. Si ces actions incluent des opérations LMD sur les tables, tous les déclencheurs présents au niveau des tables de base sont exécutés. Les déclencheurs de base de données peuvent être des déclencheurs système sur une base de données ou un schéma. Dans le cas d'une base de données, les déclencheurs s'exécutent pour chaque événement et pour tous les utilisateurs ; dans le cas d'un schéma, ils s'exécutent pour chaque événement concernant l'utilisateur correspondant. Le cours suivant aborde la création de déclencheurs de base de données. La création de déclencheurs de base de données en fonction d'événements système est présentée au chapitre "Autres concepts relatifs aux déclencheurs".

4 Règles relatives à la conception de déclencheurs
Il est conseillé de concevoir des déclencheurs pour : exécuter des actions associées centraliser des opérations globales Leur conception est à proscrire : lorsque la fonctionnalité est déjà intégrée au serveur Oracle lorsqu'ils constituent des doublons d'autres déclencheurs Si le code PL/SQL est très long, créer des procédures stockées et les appeler dans un déclencheur L'utilisation excessive de déclencheurs peut entraîner des interdépendances complexes dont la gestion peut s'avérer difficile dans les applications volumineuses Règles relatives à la conception de déclencheurs Utilisez des déclencheurs pour vous assurer que, lors de l'exécution d'une opération spécifique, les actions associées seront également exécutées. Utilisez les déclencheurs de base de données uniquement pour les opérations globales et centralisées qui doivent être exécutées pour l'instruction de déclenchement, quel que soit l'utilisateur ou l'application à l'origine de l'instruction. Ne définissez pas de déclencheur pour dupliquer ou remplacer une fonctionnalité déjà intégrée à la base de données Oracle. Par exemple, vous ne devez pas définir de déclencheur pour appliquer les règles d'intégrité qui peuvent être réalisées en utilisant des contraintes déclaratives. Procédez comme suit pour vous souvenir de l'ordre de conception d'une règle : Utilisez des contraintes intégrées au serveur Oracle telles que les clés primaires ou les clés étrangères. Développez un déclencheur de base de données ou une application telle qu'un servlet ou Enterprise JavaBean (EJB) au niveau (tier) intermédiaire. Utilisez une interface de présentation telle qu'Oracle Forms, du code HTML dynamique, des pages JSP (JavaServer Pages), etc. si vous ne pouvez pas développer votre règle (qui peut être une règle de présentation) comme indiqué ci-dessus. L'utilisation excessive de déclencheurs peut entraîner des interdépendances complexes dont la gestion peut s'avérer difficile dans les applications volumineuses. Utilisez les déclencheurs uniquement lorsque cela s'avère nécessaire ; en outre, prenez garde aux effets récursifs et en cascade. Si le code du déclencheur est très long, créez des procédures stockées contenant ce code et appelez-les dans le corps du déclencheur. Les déclencheurs de base de données s'exécutent pour tous les utilisateurs, chaque fois que l'événement pour lequel ils sont créés se produit.

5 Exemple de déclencheur de base de données
Application INSERT INTO EMPLOYEES . . .; Table EMPLOYEES Déclencheur CHECK_SAL Exemple de déclencheur de base de données Dans l'exemple, le déclencheur de base de données CHECK_SAL vérifie les valeurs correspondant aux salaires lorsqu'une application tente d'insérer une ligne dans la table EMPLOYEES. Les valeurs qui se situent en dehors des limites par rapport à la catégorie du poste peuvent être refusées ou acceptées et enregistrées dans une table d'audit.

6 Créer des déclencheurs LMD
Une instruction de déclenchement comporte les éléments suivants : moment du déclenchement pour une table : BEFORE, AFTER pour une vue : INSTEAD OF événement déclencheur : INSERT, UPDATE ou DELETE nom de la table : sur la table ou la vue type de déclencheur : ligne ou instruction clause WHEN : condition restrictive corps du déclencheur : bloc PL/SQL Déclencheur de base de données Avant de coder le corps du déclencheur, vous devez définir les valeurs de ses composants : le moment du déclenchement, l'événement déclencheur et le type de déclencheur. Si plusieurs déclencheurs sont définis pour une table, n'oubliez pas que l'ordre d'exécution de plusieurs déclencheurs de même type est arbitraire. Pour vous assurer que les déclencheurs de même type sont exécutés dans un ordre déterminé, regroupez-les dans un même déclencheur qui appellera les différentes procédures dans l'ordre voulu.

7 Composants des déclencheurs LMD
Moment du déclenchement : à quel moment le déclencheur doit-il s'exécuter ? BEFORE : exécution du corps du déclencheur avant le déclenchement de l'événement LMD sur une table AFTER : exécution du corps du déclencheur après le déclenchement de l'événement LMD sur une table INSTEAD OF : exécution du corps du déclencheur au lieu de l'instruction de déclenchement. Ce déclencheur est utilisé pour les vues qui ne peuvent pas être modifiées autrement Déclencheurs BEFORE Ce type de déclencheur est fréquemment utilisé dans les cas suivants : pour déterminer si l'exécution de l'instruction de déclenchement doit être autorisée. Ceci permet d'éviter un traitement inutile de l'instruction de déclenchement ainsi que son éventuelle annulation (rollback) si l'action de déclenchement génère une exception, pour obtenir des valeurs de colonne avant d'exécuter une instruction de déclenchement INSERT ou UPDATE, pour initialiser des variables ou indicateurs globaux, et valider des règles complexes. Déclencheurs AFTER pour exécuter l'instruction de déclenchement avant l'action de déclenchement, pour effectuer différentes actions à partir de la même instruction de déclenchement s'il existe déjà un déclencheur BEFORE. Déclencheurs INSTEAD OF Ce type de déclencheur permet de modifier, en toute transparence, les vues qu'il est impossible de modifier directement en utilisant les instructions SQL LMD, en raison de leur nature non modifiable. Vous pouvez écrire des instructions INSERT, UPDATE et DELETE liées à la vue. Le déclencheur INSTEAD OF s'exécute en arrière-plan ; il effectue directement sur les tables sous-jacentes l'action codée dans le corps du déclencheur.

8 Composants des déclencheurs LMD
Evénement utilisateur déclencheur : quelle instruction LMD entraîne l'exécution du déclencheur ? Vous pouvez utiliser les instructions suivantes : INSERT UPDATE DELETE Evénement déclencheur L'événement déclencheur ou l'instruction de déclenchement peut être une instruction INSERT, UPDATE ou DELETE exécutée sur une table. Lorsque l'événement déclencheur est une instruction UPDATE, vous pouvez indiquer une liste de colonnes afin d'identifier les colonnes dont la modification lancera l'exécution du déclencheur. Vous ne pouvez pas indiquer de liste de colonnes dans le cas des instructions INSERT et DELETE, car elles s'appliquent toujours à des lignes complètes. . . . UPDATE OF salary . . . L'événement déclencheur peut contenir une ou deux des opérations LMD ci-après, ou les trois. . . . INSERT or UPDATE or DELETE . . . INSERT or UPDATE OF job_id . . .

9 Composants des déclencheurs LMD
Type de déclencheur : le corps du déclencheur doit-il s'exécuter une seule fois ou pour chaque ligne concernée par l'instruction ? Instruction : le corps du déclencheur s'exécute une seule fois pour l'événement déclencheur. Il s'agit du comportement par défaut. Un déclencheur sur instruction s'exécute une fois, même si aucune ligne n'est affectée Ligne : le corps du déclencheur s'exécute une fois pour chaque ligne concernée par l'événement déclencheur. Un déclencheur sur ligne ne s'exécute pas si l'événement déclencheur n'affecte aucune ligne Déclencheurs sur instruction et sur ligne Vous pouvez indiquer que le déclencheur s'exécutera une fois pour chaque ligne concernée par l'instruction de déclenchement (telle qu'une instruction UPDATE sur plusieurs lignes) ou une seule fois pour l'instruction de déclenchement, quel que soit le nombre de lignes affectées. Déclencheur sur instruction Un déclencheur sur instruction s'exécute une fois pour le compte de l'événement déclencheur, même si aucune ligne n'est affectée. Ce type de déclencheur s'avère particulièrement utile si l'action ne dépend pas des données des lignes concernées ou des données fournies par l'événement déclencheur. C'est le cas par exemple pour un déclencheur qui exécute un contrôle de sécurité complexe sur l'utilisateur en cours. Déclencheur sur ligne Un déclencheur sur ligne s'exécute chaque fois que la table est affectée par l'événement déclencheur. Si l'événement déclencheur n'affecte aucune ligne, le déclencheur n'est pas exécuté. Ce type de déclencheur s'avère particulièrement utile si l'action dépend des données des lignes concernées ou des données fournies par l'événement déclencheur.

10 Composants des déclencheurs LMD
Corps du déclencheur : quelle action le déclencheur doit-il effectuer ? Le corps du déclencheur est un bloc PL/SQL ou un appel de procédure Corps du déclencheur L'action du déclencheur définit les opérations qui seront effectuées si l'événement déclencheur se produit. Le bloc PL/SQL peut contenir des instructions SQL et PL/SQL, et définir des structures PL/SQL telles que des variables, des curseurs, des exceptions, etc. Vous pouvez également appeler une procédure PL/SQL ou Java. Par ailleurs, les déclencheurs sur ligne utilisent des noms de corrélation pour accéder aux anciennes ou nouvelles valeurs de colonne de la ligne en cours de traitement. Remarque : La taille d'un déclencheur est limitée à 32 Ko.

11 Séquence d'exécution … Instruction LMD Action de déclenchement
Lorsque la manipulation concerne une seule ligne, utilisez la séquence d'exécution suivante pour un déclencheur sur une table : Instruction LMD INSERT INTO departments (department_id, department_name, location_id) VALUES (400, 'CONSULTING', 2400); Action de déclenchement Déclencheur sur instruction BEFORE Créer des déclencheurs sur instruction ou sur ligne Vous pouvez créer un déclencheur sur instruction ou sur ligne selon que le déclencheur doit s'exécuter une fois pour chaque ligne affectée par l'instruction de déclenchement, ou une seule fois pour l'instruction, quel que soit le nombre de lignes affectées. Si l'instruction de manipulation de données à l'origine du déclenchement concerne une seule ligne, les déclencheurs sur instruction et sur ligne sont tous deux exécutés à une seule reprise. Exemple Dans l'instruction SQL de l'exemple ci-dessus, aucune distinction n'est faite entre les déclencheurs sur instruction et sur ligne, car seule une ligne est insérée dans la table. Déclencheur sur ligne BEFORE Déclencheur sur ligne AFTER Déclencheur sur instruction AFTER

12 Séquence d'exécution Lorsque la manipulation concerne plusieurs lignes, utilisez la séquence d'exécution suivante pour un déclencheur sur une table : UPDATE employees SET salary = salary * 1.1 WHERE department_id = 30; Déclencheur sur instruction BEFORE Déclencheur sur ligne BEFORE Déclencheur sur ligne AFTER ... Créer des déclencheurs sur instruction ou sur ligne (suite) Si l'instruction de manipulation de données à l'origine du déclenchement concerne plusieurs lignes, le déclencheur sur instruction s'exécute à une seule reprise, tandis que le déclencheur sur ligne s'exécute une fois pour chaque ligne affectée. Exemple Dans l'instruction SQL présentée dans la diapositive, le nombre d'exécutions du déclencheur de niveau ligne correspond au nombre de lignes répondant à la clause WHERE (à savoir, le nombre d'employés appartenant au service 30). Déclencheur sur instruction AFTER

13 Syntaxe pour la création de déclencheurs sur instruction LMD
CREATE [OR REPLACE] TRIGGER trigger_name timing event1 [OR event2 OR event3] ON table_name trigger_body Remarque : Les noms des déclencheurs doivent être uniques au sein d'un même schéma Syntaxe pour la création d'un déclencheur sur instruction Les noms des déclencheurs doivent être uniques au sein d'un même schéma. En revanche, ils ne doivent pas nécessairement être uniques par rapport aux autres objets de schéma tels que les tables, les vues et les procédures. L'utilisation de noms de colonne avec la clause UPDATE dans le déclencheur permet de garantir de meilleures performances, car le déclencheur s'exécute uniquement lorsque les colonnes indiquées sont mises à jour, ce qui évite toute exécution non souhaitée en cas de mise à jour d'autres colonnes.

14 Créer des déclencheurs sur instruction LMD
Exemple : CREATE OR REPLACE TRIGGER secure_emp BEFORE INSERT ON employees BEGIN IF (TO_CHAR(SYSDATE,'DY') IN ('SAT','SUN')) OR (TO_CHAR(SYSDATE,'HH24:MI') NOT BETWEEN '08:00' AND '18:00') THEN RAISE_APPLICATION_ERROR (-20500,'You may insert into EMPLOYEES table only during business hours.'); END IF; END; / Créer des déclencheurs sur instruction LMD Vous pouvez créer un déclencheur sur instruction BEFORE afin d'empêcher l'aboutissement d'une opération de déclenchement en cas de violation d'une condition déterminée. Par exemple, vous pouvez créer un déclencheur chargé de limiter les insertions dans la table EMPLOYEES à certaines heures ouvrables, du lundi au vendredi. Si un utilisateur tente d'insérer une ligne dans la table EMPLOYEES un samedi, un message approprié s'affiche, le déclencheur échoue et l'instruction de déclenchement est annulée. N'oubliez pas que RAISE_APPLICATION_ERROR est une procédure côté serveur intégrée qui renvoie une erreur à l'utilisateur et provoque l'échec du bloc PL/SQL. En cas d'échec d'un déclencheur de base de données, le serveur Oracle annule automatiquement l'instruction de déclenchement.

15 Tester SECURE_EMP INSERT INTO employees (employee_id, last_name, first_name, , hire_date, job_id, salary, department_id) VALUES (300, 'Smith', 'Rob', 'RSMITH', SYSDATE, 'IT_PROG', 4500, 60); Exemple Tentez d'insérer une ligne dans la table EMPLOYEES en dehors des heures ouvrables. Lorsque la date et l'heure ne correspondent pas aux horaires d'ouverture indiqués dans le déclencheur, un message d'erreur semblable à celui présenté dans la diapositive s'affiche.

16 Utiliser des prédicats conditionnels
CREATE OR REPLACE TRIGGER secure_emp BEFORE INSERT OR UPDATE OR DELETE ON employees BEGIN IF (TO_CHAR (SYSDATE,'DY') IN ('SAT','SUN')) OR (TO_CHAR (SYSDATE, 'HH24') NOT BETWEEN '08' AND '18') THEN IF DELETING THEN RAISE_APPLICATION_ERROR (-20502,'You may delete from EMPLOYEES table only during business hours.'); ELSIF INSERTING THEN RAISE_APPLICATION_ERROR (-20500,'You may insert into EMPLOYEES table only during business hours.'); ELSIF UPDATING ('SALARY') THEN RAISE_APPLICATION_ERROR (-20503,'You may update SALARY only during business hours.'); ELSE RAISE_APPLICATION_ERROR (-20504,'You may update EMPLOYEES table only during normal hours.'); END IF; END; Combiner des événements déclencheurs Vous pouvez rassembler plusieurs événements déclencheurs au sein d'un seul événement en utilisant les prédicats conditionnels spéciaux INSERTING, UPDATING et DELETING dans le corps du déclencheur. Exemple Créez un déclencheur pour empêcher l'exécution de tout événement de manipulation de données sur la table EMPLOYEES en dehors de certaines heures ouvrables, du lundi au vendredi.

17 Créer un déclencheur sur ligne LMD
Syntaxe : CREATE [OR REPLACE] TRIGGER trigger_name timing event1 [OR event2 OR event3] ON table_name [REFERENCING OLD AS old | NEW AS new] FOR EACH ROW [WHEN (condition)] trigger_body Syntaxe pour la création d'un déclencheur sur ligne

18 Créer des déclencheurs sur ligne LMD
CREATE OR REPLACE TRIGGER restrict_salary BEFORE INSERT OR UPDATE OF salary ON employees FOR EACH ROW BEGIN IF NOT (:NEW.job_id IN ('AD_PRES', 'AD_VP')) AND :NEW.salary > 15000 THEN RAISE_APPLICATION_ERROR (-20202,'Employee cannot earn this amount'); END IF; END; / Créer un déclencheur sur ligne Vous pouvez créer un déclencheur sur ligne BEFORE afin d'empêcher l'aboutissement d'une opération de déclenchement en cas de violation d'une condition déterminée. Créez un déclencheur permettant uniquement à certains employés de percevoir un salaire supérieur à 15 000. Si un utilisateur tente d'enfreindre cette condition, le déclencheur génère une erreur. UPDATE employees SET salary = 15500 WHERE last_name = 'Russell';

19 Utiliser les qualificatifs OLD et NEW
CREATE OR REPLACE TRIGGER audit_emp_values AFTER DELETE OR INSERT OR UPDATE ON employees FOR EACH ROW BEGIN INSERT INTO audit_emp_table (user_name, timestamp, id, old_last_name, new_last_name, old_title, new_title, old_salary, new_salary) VALUES (USER, SYSDATE, :OLD.employee_id, :OLD.last_name, :NEW.last_name, :OLD.job_id, :NEW.job_id, :OLD.salary, :NEW.salary ); END; / Utiliser les qualificatifs OLD et NEW Dans un déclencheur sur ligne, faites référence à la valeur d'une colonne avant et après la modification des données, en la faisant précéder du qualificatif OLD ou NEW. Les qualificatifs OLD et NEW sont disponibles uniquement dans les déclencheurs sur ligne. Ils doivent être précédés du signe deux-points (:) dans toutes les instructions SQL et PL/SQL. Ne pas utiliser le préfixe (:) quand les qualificatifs sont référencés dans la condition de restriction WHEN. Remarque : Les déclencheurs sur ligne peuvent entraîner une baisse de performances si vous effectuez de nombreuses mises à jour sur des tables volumineuses.

20 Utiliser les qualificatifs OLD et NEW : exemple de la table Audit_Emp_Table
INSERT INTO employees (employee_id, last_name, job_id, salary, ...) VALUES (999, 'Temp emp', 'SA_REP', 1000, ...); UPDATE employees SET salary = 2000, last_name = 'Smith' WHERE employee_id = 999; Utiliser les qualificatifs OLD et NEW : exemple de la table AUDIT_EMP_TABLE Créez un déclencheur sur la table EMPLOYEES pour ajouter des lignes à la table utilisateur AUDIT_EMP_TABLE et consigner ainsi les activités d'un utilisateur par rapport à la table EMPLOYEES. Le déclencheur enregistre les valeurs de plusieurs colonnes avant et après les modifications de données en utilisant les qualificatifs OLD et NEW avec le nom de colonne approprié. La table AUDIT_EMP_TABLE comporte également une colonne COMMENTS supplémentaire, qui n'apparaît pas dans la diapositive. SELECT user_name, timestamp, ... FROM audit_emp_table

21 Restreindre l'action d'un déclencheur sur ligne
CREATE OR REPLACE TRIGGER derive_commission_pct BEFORE INSERT OR UPDATE OF salary ON employees FOR EACH ROW WHEN (NEW.job_id = 'SA_REP') BEGIN IF INSERTING THEN :NEW.commission_pct := 0; ELSIF :OLD.commission_pct IS NULL ELSE :NEW.commission_pct := :OLD.commission_pct ; END IF; END; / Exemple La clause WHEN permet de limiter l'action du déclencheur aux lignes qui répondent à une condition déterminée. Vous pouvez créer un déclencheur sur la table EMPLOYEES pour calculer la commission d'un employé lors de l'ajout d'une ligne à cette table ou lors de la modification du salaire d'un employé. Le qualificatif NEW ne peut pas être précédé d'un signe deux-points dans la clause WHEN, car celle-ci se trouve en dehors des blocs PL/SQL.

22 Déclencheurs INSTEAD OF
Application INSERT INTO my_view . . .; MY_VIEW Déclencheur INSTEAD OF INSERT TABLE1 Déclencheurs INSTEAD OF Les déclencheurs INSTEAD OF vous permettent de modifier les données, lorsqu'une instruction LMD est exécutée pour une vue qui, par nature, ne peut pas être mise à jour. On parle de déclencheurs INSTEAD OF, car contrairement aux autres déclencheurs, le serveur Oracle les exécute à la place de l'instruction de déclenchement. Ce type de déclencheur permet d'effectuer directement les opérations INSERT, UPDATE ou DELETE sur les tables sous-jacentes. Vous pouvez écrire des instructions INSERT, UPDATE ou DELETE par rapport à une vue et laisser le déclencheur INSTEAD OF s'exécuter en arrière-plan réaliser les actions appropriées. Pourquoi utiliser les déclencheurs INSTEAD OF ? Vous ne pouvez pas modifier une vue en utilisant les instructions LMD standard, si l'interrogation de la vue contient des opérateurs définis, des fonctions de groupe, des clauses telles que GROUP BY, CONNECT BY, START, l'opérateur DISTINCT ou des jointures. Par exemple, si une vue comporte plusieurs tables, une opération d'insertion la concernant peut entraîner une insertion dans une table et une mise à jour dans une autre. Vous pouvez donc créer un déclencheur INSTEAD OF qui s'exécute lorsque vous effectuez une insertion dans la vue. Dans ce cas, le corps du déclencheur s'exécute à la place de l'insertion d'origine, ce qui se traduit par l'insertion de données dans une table et la mise à jour de l'autre. Remarque : Si une vue qui peut être mise à jour de manière intrinsèque possède des déclencheurs INSTEAD OF, ces derniers ont priorité. Les déclencheurs INSTEAD OF sont des déclencheurs sur ligne. L'option CHECK des vues n'est pas appliquée lorsque des insertions ou des mises jour sont effectuées sur la vue en utilisant des déclencheurs INSTEAD OF. Le corps du déclencheur INSTEAD OF doit appliquer la vérification. UPDATE TABLE2

23 Créer un déclencheur INSTEAD OF
Syntaxe : CREATE [OR REPLACE] TRIGGER trigger_name INSTEAD OF event1 [OR event2 OR event3] ON view_name [REFERENCING OLD AS old | NEW AS new] [FOR EACH ROW] trigger_body Syntaxe pour la création d'un déclencheur INSTEAD OF Remarque : Les déclencheurs INSTEAD OF ne peuvent être écrits que pour des vues. Les options BEFORE et AFTER ne sont pas valides.

24 Hidden slide Créer un déclencheur INSTEAD OF Exemple :
L'exemple ci-dessous crée deux tables, NEW_EMPS et NEW_DEPTS, basées respectivement sur les tables EMPLOYEES et DEPARTMENTS. Une vue EMP_DETAILS est également créée à partir des tables EMPLOYEES et DEPARTMENTS. L'exemple crée aussi un déclencheur INSTEAD OF, nommé NEW_EMP_DEPT. Lorsqu'une ligne est insérée dans la vue EMP_DETAILS, l'insertion ne s'effectue pas directement ; elle s'effectue dans les tables NEW_EMPS et NEW_DEPTS en fonction des données de l'instruction INSERT. De même, lorsqu'une ligne est modifiée ou supprimée dans la vue EMP_DETAILS, ce sont les lignes correspondantes des tables NEW_EMPS et NEW_DEPTS qui sont affectées. CREATE TABLE new_emps AS SELECT employee_id, last_name, salary, department_id, , job_id, hire_date FROM employees; CREATE TABLE new_depts AS SELECT d.department_id, d.department_name, d.location_id, sum(e.salary) tot_dept_sal FROM employees e, departments d WHERE e.department_id = d.department_id GROUP BY d.department_id, d.department_name, d.location_id; CREATE VIEW emp_details AS SELECT e.employee_id, e.last_name, e.salary, e.department_id, e. , e.job_id, d.department_name, d.location_id WHERE e.department_id = d.department_id; CREATE OR REPLACE TRIGGER new_emp_dept INSTEAD OF INSERT OR UPDATE OR DELETE ON emp_details FOR EACH ROW BEGIN IF INSERTING THEN INSERT INTO new_emps VALUES (:NEW.employee_id, :NEW.last_name, :NEW.salary, :NEW.department_id, :NEW. , :New.job_id, SYSDATE); UPDATE new_depts SET tot_dept_sal = tot_dept_sal + :NEW.salary WHERE department_id = :NEW.department_id; ELSIF DELETING THEN DELETE FROM new_emps WHERE employee_id = :OLD.employee_id; SET tot_dept_sal = tot_dept_sal - :OLD.salary WHERE department_id = :OLD.department_id; Hidden slide

25 Hidden slide Créer un déclencheur INSTEAD OF (suite) Exemple :
ELSIF UPDATING ('salary') THEN UPDATE new_emps SET salary = :NEW.salary WHERE employee_id = :OLD.employee_id; UPDATE new_depts SET tot_dept_sal = tot_dept_sal + (:NEW.salary - :OLD.salary) WHERE department_id = :OLD.department_id; ELSIF UPDATING ('department_id') SET department_id = :NEW.department_id SET tot_dept_sal = tot_dept_sal - :OLD.salary SET tot_dept_sal = tot_dept_sal + :NEW.salary WHERE department_id = :NEW.department_id; END IF; END; / Remarque : Une explication graphique de cet exemple est présentée à la page suivante.

26 Créer un déclencheur INSTEAD OF
Exécution d'une instruction INSERT dans la vue EMP_DETAILS basée sur les tables EMPLOYEES et DEPARTMENTS INSERT INTO emp_details(employee_id, ... ) VALUES(9001,'ABBOTT',3000,10,'abbott.mail.com','HR_MAN'); 1 Opération INSERT d'un déclencheur INSTEAD OF dans EMP_DETAILS Créer un déclencheur INSTEAD OF Vous pouvez créer un déclencheur INSTEAD OF pour gérer les tables de base sur lesquelles repose une vue. Supposons qu'un nom d'employé soit inséré en utilisant la vue EMP_DETAILS créée à partir des tables EMPLOYEES et DEPARTMENTS. Créez un déclencheur qui effectue les opérations d'insertion (INSERT) et de mise à jour (UPDATE) appropriées dans les tables de base. La diapositive de la page suivante décrit le comportement du déclencheur INSTEAD OF dans cette situation.

27 Créer un déclencheur INSTEAD OF
Exécution d'une instruction INSERT dans la vue EMP_DETAILS basée sur les tables EMPLOYEES et DEPARTMENTS INSERT INTO emp_details(employee_id, ... ) VALUES(9001,'ABBOTT',3000,10,'abbott.mail.com','HR_MAN'); 1 Opération INSERT d'un déclencheur INSTEAD OF dans EMP_DETAILS INSERT dans NEW_EMPS UPDATE NEW_DEPTS 2 3 Créer un déclencheur INSTEAD OF (suite) Le déclencheur INSTEAD OF dans la vue EMP_DETAILS provoque les opérations suivantes, au lieu d'insérer le nouvel enregistrement d'employé dans la table EMPLOYEES : Une ligne est insérée dans la table NEW_EMPS. La colonne TOTAL_DEPT_SAL de la table NEW_DEPTS est mise à jour. Le salaire indiqué pour le nouvel employé est ajouté au montant total des salaires du service auquel l'employé a été affecté.

28 Différences entre les déclencheurs de base de données et les procédures stockées
Définis via la commande CREATE TRIGGER Le dictionnaire de données contient le code source dans USER_TRIGGERS Appel implicite Les instructions COMMIT, SAVEPOINT et ROLLBACK ne sont pas autorisées Procédures Définis via la commande CREATE PROCEDURE Le dictionnaire de données contient le code source dans USER_SOURCE Appel explicite Les instructions COMMIT, SAVEPOINT et ROLLBACK sont autorisées Déclencheurs de base de données et procédures stockées Les déclencheurs de base de données et les procédures stockées présentent les différences suivantes : Les déclencheurs sont totalement compilés lorsque la commande CREATE TRIGGER est exécutée et leur pseudo-code est stocké dans le dictionnaire de données. L'apparition d'erreurs lors de la compilation d'un déclencheur n'empêche pas sa création.

29 Différences entre les déclencheurs de base de données et les déclencheurs Form Builder
INSERT INTO EMPLOYEES . . .; Table EMPLOYEES Déclencheur CHECK_SAL BEFORE INSERT ligne Différences entre les déclencheurs de base de données et les déclencheurs Form Builder Les déclencheurs de base de données et les déclencheurs Form Builder présentent les différences suivantes :

30 Gérer les déclencheurs
Désactiver ou réactiver un déclencheur de base de données : ALTER TRIGGER trigger_name DISABLE | ENABLE Désactiver ou réactiver tous les déclencheurs d'une table : ALTER TABLE table_name DISABLE | ENABLE ALL TRIGGERS Recompiler un déclencheur pour une table : ALTER TRIGGER trigger_name COMPILE Modes des déclencheurs : activé ou désactivé Un déclencheur est automatiquement activé lors de sa création. Le serveur Oracle vérifie les contraintes d'intégrité des déclencheurs activés et s'assure que ces derniers ne pourront pas y porter atteinte. Par ailleurs, il fournit des vues cohérentes en lecture pour les interrogations et les contraintes, gère les dépendances et propose un processus de validation à deux phases si un déclencheur met à jour des tables distantes dans une base de données distribuée. Utilisez la syntaxe ALTER TRIGGER pour désactiver un déclencheur spécifique ou ALTER TABLE pour désactiver tous les déclencheurs d'une table. Désactivez un déclencheur pour obtenir de meilleures performances ou éviter les contrôles d'intégrité lors du chargement de gros volumes de données à l'aide d'utilitaires tels que SQL*Loader. Vous pouvez également être amené à désactiver un déclencheur s'il fait référence à un objet de base de données actuellement indisponible en raison d'un échec de connexion réseau, d'un incident de disque, ou de la mise hors ligne (offline) d'un fichier de données ou d'un tablespace. Compiler un déclencheur Utilisez la commande ALTER TRIGGER pour recompiler explicitement un déclencheur non valide. Lorsque vous exécutez une instruction ALTER TRIGGER avec l'option COMPILE, la recompilation est effectuée, que le déclencheur soit valide ou non.

31 Syntaxe DROP TRIGGER Pour supprimer un déclencheur de la base de
données, utiliser la syntaxe DROP TRIGGER : DROP TRIGGER trigger_name; Exemple: DROP TRIGGER secure_emp; Supprimer des déclencheurs Lorsqu'un déclencheur n'est plus nécessaire, vous pouvez le supprimer en utilisant une instruction SQL dans iSQL*Plus. Remarque : Lorsqu'une table est supprimée, tous ses déclencheurs sont également supprimés

32 Tests des déclencheurs
Tester toutes les opérations sur les données qui provoquent un déclenchement, ainsi que celles n'en produisent pas Tester chaque cas de la clause WHEN Provoquer une exécution directe du déclencheur via une opération de base sur les données, et une exécution indirecte via une procédure Tester l'impact du déclencheur sur les autres déclencheurs Tester l'impact des autres déclencheurs sur le déclencheur Tester les déclencheurs Vérifiez le bon fonctionnement du déclencheur en testant séparément un certain nombre de cas de figure. Utilisez les procédures DBMS_OUTPUT pour déboguer les déclencheurs ; vous pouvez aussi utiliser l'outil de débogage Procedure Builder. L'utilisation de Procedure Builder est traitée dans l'annexe F, "Créer des programmes en utilisant Procedure Builder".

33 Modèle d'exécution des déclencheurs et vérification des contraintes
1. Exécuter tous les déclencheurs BEFORE STATEMENT. 2. Effectuer une boucle pour toutes les lignes affectées : a. exécuter tous les déclencheurs BEFORE ROW b. exécuter tous les déclencheurs AFTER ROW 3. Exécuter l'instruction LMD et vérifier les contraintes d'intégrité. 4. Exécuter tous les déclencheurs AFTER STATEMENT. Modèle d'exécution des déclencheurs Une même instruction LMD peut exécuter jusqu'à quatre types de déclencheur (BEFORE, AFTER, sur instruction et sur ligne). Un événement déclencheur ou une instruction du déclencheur peut entraîner la vérification d'une ou plusieurs contraintes d'intégrité. Les déclencheurs peuvent également entraîner l'exécution d'autres déclencheurs (déclencheurs en cascade). Toutes les actions et vérifications effectuées à la suite d'une instruction SQL doivent aboutir. Si une exception a lieu dans un déclencheur, et si elle n'est pas traitée explicitement, toutes les actions effectuées à la suite de l'instruction SQL d'origine sont annulées, y compris celles effectuées en exécutant des déclencheurs. Ceci garantit que les déclencheurs ne porteront jamais atteinte aux contraintes d'intégrité. Lorsqu'un déclencheur s'exécute, les tables auxquelles l'action du déclencheur fait référence peuvent être en cours de modification par les transactions d'autres utilisateurs. Dans tous les cas, une image cohérente en lecture est garantie pour les valeurs modifiées que le déclencheur doit lire (interrogation) ou écrire (mise à jour).

34 Exemple de modèle d'exécution des déclencheurs et de vérification des contraintes
UPDATE employees SET department_id = 999 WHERE employee_id = 170; -- Integrity constraint violation error CREATE OR REPLACE TRIGGER constr_emp_trig AFTER UPDATE ON employees FOR EACH ROW BEGIN INSERT INTO departments VALUES (999, 'dept999', 140, 2400); END; / Exemple de modèle d'exécution des déclencheurs et de vérification des contraintes L'exemple de la diapositive présente une situation dans laquelle la contrainte d'intégrité peut être prise en charge grâce à l'utilisation d'un déclencheur. La table EMPLOYEES possède une contrainte de clé étrangère sur la colonne DEPARTMENT_ID de la table DEPARTMENTS. Dans la première instruction SQL, la valeur 999 doit être affectée au numéro de service (DEPARTMENT_ID) de l'employé possédant le numéro 170 (EMPLOYEE_ID). Etant donné que ce service n'existe pas dans la table DEPARTMENTS, l'instruction déclenche l'exception –2292 pour violation des contraintes d'intégrité. Un déclencheur CONSTR_EMP_TRIG, qui insère un nouveau service 999 dans la table DEPARTMENTS, est créé. Lors du lancement de l'instruction UPDATE qui change le numéro de service de l'employé 170 en 999, le déclencheur s'exécute. La contrainte de clé étrangère est alors vérifiée. Puisque le déclencheur a inséré le service 999 dans la table DEPARTMENTS, la vérification de la contrainte de clé étrangère aboutit et aucune exception n'est déclenchée. Le processus est compatible avec Oracle8i et les versions ultérieures. L'exemple décrit dans la diapositive génère une erreur lors de l'exécution dans les versions antérieures à Oracle8i. UPDATE employees SET department_id = 999 WHERE employee_id = 170; -- Successful after trigger is fired

35 Démonstration type de déclencheurs utilisant des structures de package
AUDIT_EMP_TRIG FOR EACH ROW Incrémentation des variables Package VAR_PACK Instruction LMD dans la table EMPLOYEES 1 2 AUDIT_EMP_TAB AFTER STATEMENT Copie, puis réinitialisation des variables Démonstration type Les pages de sous-programmes PL/SQL suivantes illustrent l'interaction entre les déclencheurs, les procédures de package, les fonctions et les variables globales. Séquence des événements : 1. Exécution d'une commande INSERT, UPDATE ou DELETE qui permet de manipuler une ou plusieurs lignes. 2. Le déclencheur AFTER ROW, AUDIT_EMP_TRIG, appelle la procédure de package pour incrémenter les variables globales du package VAR_PACK. Etant donné qu'il s'agit d'un déclencheur sur ligne, celui-ci s'exécute une fois pour chaque ligne mise à jour. 3. Une fois l'instruction exécutée, le déclencheur AFTER STATEMENT, AUDIT_EMP_TAB, appelle la procédure AUDIT_EMP. 4. Cette procédure affecte les valeurs des variables globales aux variables locales en utilisant les fonctions de package, met à jour la table AUDIT_TABLE, puis réinitialise les variables globales. 3 AUDIT_TABLE 4

36 Déclencheurs AFTER sur ligne et sur instruction
CREATE OR REPLACE TRIGGER audit_emp_trig AFTER UPDATE or INSERT or DELETE on EMPLOYEES FOR EACH ROW BEGIN IF DELETING THEN var_pack.set_g_del(1); ELSIF INSERTING THEN var_pack.set_g_ins(1); ELSIF UPDATING ('SALARY') THEN var_pack.set_g_up_sal(1); ELSE var_pack.set_g_upd(1); END IF; END audit_emp_trig; / CREATE OR REPLACE TRIGGER audit_emp_tab AFTER UPDATE or INSERT or DELETE on employees BEGIN audit_emp; END audit_emp_tab; / Déclencheurs AFTER sur ligne et sur instruction AUDIT_EMP_TRIG est un déclencheur sur ligne qui s'exécute après la manipulation de chaque ligne. Il appelle les procédures de package en fonction du type d'instruction LMD exécuté. Par exemple, si l'instruction LMD met à jour le salaire d'un employé, le déclencheur appelle la procédure SET_G_UP_SAL. Celle-ci appelle à son tour la fonction G_UP_SAL. Cette dernière incrémente la variable de package GV_UP_SAL qui comptabilise les lignes affectées par la mise à jour du salaire. Le déclencheur AUDIT_EMP_TAB s'exécute lorsque l'instruction est terminée. Il appelle la procédure AUDIT_EMP, qui est présentée dans les pages suivantes. La procédure met à jour la table AUDIT_TABLE. Des informations sont entrées dans la table AUDIT_TABLE, notamment l'identité de l'utilisateur ayant exécuté l'instruction LMD, la table sur laquelle l'instruction a été exécutée et le nombre total de manipulations de données effectuées jusqu'ici sur la table (indiquées par la valeur de la colonne correspondante dans la table AUDIT_TABLE). Enfin, la procédure AUDIT_EMP réinitialise les variables de package en leur affectant la valeur 0.

37 Démonstration de spécification du package VAR_PACK
var_pack.sql CREATE OR REPLACE PACKAGE var_pack IS -- these functions are used to return the -- values of package variables FUNCTION g_del RETURN NUMBER; FUNCTION g_ins RETURN NUMBER; FUNCTION g_upd RETURN NUMBER; FUNCTION g_up_sal RETURN NUMBER; -- these procedures are used to modify the -- values of the package variables PROCEDURE set_g_del (p_val IN NUMBER); PROCEDURE set_g_ins (p_val IN NUMBER); PROCEDURE set_g_upd (p_val IN NUMBER); PROCEDURE set_g_up_sal (p_val IN NUMBER); END var_pack; / Démonstration du corps du package VAR_PACK var_pack_body.sql CREATE OR REPLACE PACKAGE BODY var_pack IS gv_del NUMBER := 0; gv_ins NUMBER := 0; gv_upd NUMBER := 0; gv_up_sal NUMBER := 0; FUNCTION g_del RETURN NUMBER IS BEGIN RETURN gv_del; END; FUNCTION g_ins RETURN NUMBER IS RETURN gv_ins; FUNCTION g_upd RETURN NUMBER IS RETURN gv_upd; FUNCTION g_up_sal RETURN NUMBER IS RETURN gv_up_sal; (suite à la page suivante)

38 Corps du package VAR_PACK (suite)
PROCEDURE set_g_del (p_val IN NUMBER) IS BEGIN IF p_val = 0 THEN gv_del := p_val; ELSE gv_del := gv_del +1; END IF; END set_g_del; PROCEDURE set_g_ins (p_val IN NUMBER) IS gv_ins := p_val; ELSE gv_ins := gv_ins +1; END set_g_ins; PROCEDURE set_g_upd (p_val IN NUMBER) IS gv_upd := p_val; ELSE gv_upd := gv_upd +1; END set_g_upd; PROCEDURE set_g_up_sal (p_val IN NUMBER) IS gv_up_sal := p_val; ELSE gv_up_sal := gv_up_sal +1; END set_g_up_sal; END var_pack; /

39 Démonstration d'utilisation de la procédure AUDIT_EMP
CREATE OR REPLACE PROCEDURE audit_emp IS v_del NUMBER := var_pack.g_del; v_ins NUMBER := var_pack.g_ins; v_upd NUMBER := var_pack.g_upd; v_up_sal NUMBER := var_pack.g_up_sal; BEGIN IF v_del + v_ins + v_upd != 0 THEN UPDATE audit_table SET del = del + v_del, ins = ins + v_ins, upd = upd + v_upd WHERE user_name=USER AND tablename='EMPLOYEES' AND column_name IS NULL; END IF; IF v_up_sal != 0 THEN UPDATE audit_table SET upd = upd + v_up_sal AND column_name = 'SALARY'; -- resetting global variables in package VAR_PACK var_pack.set_g_del (0); var_pack.set_g_ins (0); var_pack.set_g_upd (0); var_pack.set_g_up_sal (0); END audit_emp; Mettre à jour la table AUDIT_TABLE avec la procédure AUDIT_EMP La procédure AUDIT_EMP met à jour la table AUDIT_TABLE et appelle les fonctions du package VAR_PACK qui réinitialisent les variables de package, assurant ainsi leur préparation pour l'instruction LMD suivante.

40 Synthèse Procédure Package Déclencheur Déclaration de la procédure A
xxxxxxxxxxxxxxxxxx vvvvvvvvvvvvvvvvvv Déclaration de la procédure A Définition de la procédure B Vous pouvez développer plusieurs types de structure de base de données procédurales en fonction de leur utilisation. Définition de la procédure A Variable locale

41 Présentation de l'exercice 9
Dans cet exercice, vous allez : créer des déclencheurs sur instruction et sur ligne créer des déclencheurs avancés afin d'accroître les fonctionnalités de la base de données Oracle Présentation de l'exercice 9 Dans cet exercice, vous allez créer des déclencheurs sur instruction et sur ligne, ainsi que des procédures qui seront appelées depuis les déclencheurs.

42 Exercice 9 1. Les modifications des données sont autorisées sur les tables uniquement durant les heures ouvrables normales, de 8h45 à 17h30, du lundi au vendredi. Créez une procédure stockée nommée SECURE_DML empêchant l'exécution de l'instruction LMD en dehors des heures ouvrables normales et renvoyant le message suivant : "You may only make changes during normal office hours." 2. a. Créez un déclencheur sur instruction sur la table JOBS, qui appelle la procédure ci-dessus. b. Testez la procédure en modifiant temporairement les heures qui y sont indiquées, puis en insérant un nouvel enregistrement dans la table JOBS. Par exemple, remplacez 08h45 par 16h45 ; un message d'erreur doit s'afficher. Une fois le test effectué, réinitialisez les heures de la procédure et recréez-la comme indiqué dans la question 1 ci-dessus. Si vous avez le temps : 3. Les employés doivent recevoir automatiquement une augmentation en cas de hausse du salaire minimum associé à un poste. Mettez en oeuvre cet impératif via un déclencheur sur la table JOBS. a. Créez une procédure stockée nommée UPD_EMP_SAL pour mettre à jour le salaire. La procédure accepte deux paramètres : l'ID de poste pour lequel le salaire doit être mis à jour et le nouveau salaire minimum correspondant à l'ID de poste. La procédure s'exécute à partir du déclencheur de la table JOBS. b. Créez un déclencheur sur ligne nommé UPDATE_EMP_SALARY pour la table JOBS, qui appelle la procédure UPD_EMP_SAL lorsque le salaire minimum de la table JOBS est mis à jour pour un ID de poste spécifique. c. Interrogez la table EMPLOYEES pour afficher le salaire actuel des employés travaillant en tant que programmeurs. d. Faites passer le salaire minimum du poste de programmeur de 4 000 à 5 000. e. Le salaire de l'employée Lorentz (ID d'employé 107) est inférieur à 4 500. Vérifiez si son salaire a été augmenté à 5 000, la nouvelle valeur minimum.


Télécharger ppt "Créer des déclencheurs de base de données"

Présentations similaires


Annonces Google