FirebirdSQL logo
 VIEWPROCEDURE 

Avertissements

  1. Les déclencheurs des événements de base de données DISCONNECT et ROLLBACK ne seront pas déclenchés lorsque les clients sont désactivés via les tables de surveillance (DELETE FROM MON$ATTACHMENTS).

  2. L’utilisation de l’instruction IN AUTONOMOUS TRANSACTION DO dans les déclencheurs d’événements de la base de données liés aux transactions (COMMIT, ROLLBACK, START) peut provoquer une boucle.

Qui peut créer des déclencheurs pour les événements de la base de données ?

Des déclencheurs pour les événements de la base de données peuvent être créés :

  • Administrateurs

  • Propriétaire de la base de données ;

  • Utilisateurs avec le privilège ALTER DATABASE.

Exemples

Example 1. Créez un trigger sur un événement de connexion à une base de données pour enregistrer l’événement.
CREATE TRIGGER tr_log_connect
INACTIVE ON CONNECT POSITION 0
AS
BEGIN
  INSERT INTO LOG_CONNECT (ID,
                           USERNAME,
                           ATIME)
  VALUES (NEXT VALUE FOR SEQ_LOG_CONNECT,
          CURRENT_USER,
          CURRENT_TIMESTAMP);
END
Example 2. Créer un déclencheur pour un événement de connexion à une base de données afin de contrôler l’accès.
CREATE EXCEPTION E_INCORRECT_WORKTIME 'La journée de travail n''a pas encore commencé';

CREATE TRIGGER TR_LIMIT_WORKTIME ACTIVE
ON CONNECT POSITION 1
AS
BEGIN
  IF ((CURRENT_USER <> 'SYSDBA') AND
      NOT (CURRENT_TIME BETWEEN time '9:00' AND time '17:00')) THEN
     EXCEPTION E_INCORRECT_WORKTIME;
END
Voir aussi :

ALTER TRIGGER, DROP TRIGGER.

Déclencheurs pour les événements de changement de métadonnées

Les déclencheurs d’événements de changement de métadonnées (déclencheurs DDL) sont conçus pour fournir des restrictions qui seront appliquées aux utilisateurs qui tentent de créer, modifier ou supprimer un objet DDL.Leur autre objectif est de fournir un journal des changements de métadonnées.

Les déclencheurs pour les événements de changement de métadonnées sont une sous-espèce des déclencheurs d’événements de base de données.

Caractéristiques :

  1. Les déclencheurs BEFORE sont exécutés avant les modifications des tables du système. Les déclencheurs AFTER sont exécutés après les modifications apportées aux tables du système.

  2. Lorsqu’une instruction DDL déclenche un déclencheur dans lequel une exception est levée (BEFORE ou AFTER, intentionnellement ou non), l’instruction ne sera pas corrigée. En d’autres termes, les exceptions peuvent être utilisées pour s’assurer que l’instruction DDL est remplacée si certaines conditions ne sont pas remplies.

  3. Les actions de déclenchement DDL ne sont exécutées que lorsque la transaction dans laquelle l’instruction DDL concernée est exécutée est validée. N’oubliez jamais que dans un trigger AFTER, seul ce qui peut être fait après une commande DDL, sans commiter automatiquement les transactions, est possible. Vous ne pouvez pas, par exemple, créer une table dans le déclencheur et l’utiliser là.

  4. Pour les instructions CREATE OR ALTER …​, le déclencheur est déclenché une fois pour un événement CREATE ou ALTER, selon que l’objet existait ou non auparavant. Pour les opérateurs RECREATE, le trigger est déclenché pour l’événement DROP si l’objet existait et ensuite pour l’événement CREATE.

  5. Si l’objet de métadonnées n’existe pas, les déclencheurs des événements ALTER et DROP ne sont normalement pas déclenchés. Les exceptions sont décrites dans la clause 6.

  6. L’exception à la règle 5 sont les déclencheurs BEFORE {ALTER | DROP} USER, qui seront appelés même si le nom d’utilisateur n’existe pas. Cela est dû au fait que ces commandes sont exécutées pour une base de données de sécurité pour laquelle aucune vérification de l’existence de l’utilisateur n’est effectuée avant leur exécution. Ce comportement est susceptible d’être différent pour les utilisateurs embarqués, donc n’écrivez pas de code qui en dépende.

  7. Si une exception est levée après le début de l’exécution de la commande DDL et avant l’exécution du déclencheur AFTER, celui-ci n’est pas exécuté.

  8. Les déclencheurs individuels {CREATE | ALTER | DROP} ne sont pas lancés pour les procédures et les fonctions au sein des packages. {PROCÉDURE | FONCTION}.

  9. L’instruction ALTER DOMAIN old name TO new name définit les variables contextuelles OLD_OBJECT_NAME et NEW_OBJECT_NAME dans les déclencheurs BEFORE et AFTER. La variable contextuelle OBJECT_NAME contiendra l’ancien nom de l’objet de métadonnées dans le déclencheur BEFORE et le nouveau nom dans le déclencheur AFTER.

Si ANY DDL STATEMENT est spécifié comme événement, le déclencheur sera invoqué lorsque l’un des événements DDL se produira.

L’espace des noms DDL_TRIGGER

Pendant que le déclencheur DDL est en cours d’exécution, l’espace de noms DL_TRIGGER est disponible pour être utilisé dans la fonction RDB$GET_CONTEXT.Son utilisation est également autorisée dans les procédures stockées et les fonctions appelées par des déclencheurs DDL.

Le contexte DDL_TRIGGER agit comme une pile.Avant de déclencher un déclencheur DDL, les valeurs liées à la commande en cours d’exécution sont placées sur cette pile.Lorsque le déclenchement est terminé, les valeurs sont éjectées.Ainsi.Dans le cas d’instructions DDL en cascade, lorsque chaque commande DDL utilisateur déclenche un déclencheur DDL, et que ce déclencheur déclenche d’autres commandes DDL, avec EXECUTE STATEMENT, les valeurs des variables dans l’espace de noms DDL_TRIGGER correspondront à la commande qui a déclenché le dernier déclencheur DDL dans la pile d’appels.

Variables disponibles dans l’espace de noms DDL_TRIGGER
  • EVENT_TYPE - type d’événement (CREATE, ALTER, DROP)

  • OBJECT_TYPE - type d’objet (TABLE, VIEW etc.)

  • DDL_EVENT - nom de l’événement (<ddl event item>),

    <ddl event item> = EVENT_TYPE || '' || OBJECT_TYPE

  • OBJECT_NAME - nom de l’objet de métadonnées

  • OLD_OBJECT_NAME - nom de l’objet de métadonnées avant le renommage.

  • NEW_OBJECT_NAME - nom de l’objet de métadonnées après le renommage.

  • SQL_TEXT - texte de la requête SQL

Supprimer un déclencheur

De nouvelles clés ont été ajoutées à certains utilitaires de ligne de commande Firebird pour désactiver les trigger dans la base de données:

gbak -nodbtriggers
isql -nodbtriggers
nbackup -T

Ces clés ne peuvent être utilisées que par SYSDBA ou le propriétaire de la base de données.

Qui peut créer des triggers pour les événements de changement de métadonnées ?

Des déclencheurs pour les événements de changement de métadonnées peuvent être créés :

  • Administrateurs

  • Propriétaire de la base de données ;

  • Utilisateurs avec le privilège `ALTER DATABASE'.

Exemples

Example 1. Contrôle des objets de base de données à l’aide d’un déclencheur DDL
CREATE EXCEPTION e_invalid_sp_name 'Mauvais nom de la procédure stockée (devrait commencer par SP_)';

SET TERM !;

CREATE TRIGGER trig_ddl_sp BEFORE CREATE PROCEDURE
AS
BEGIN
  IF (rdb$get_context('DDL_TRIGGER', 'OBJECT_NAME')
      NOT STARTING 'SP_') THEN
    EXCEPTION e_invalid_sp_name;
END!

-- Test
CREATE PROCEDURE sp_test
AS
BEGIN
END!

CREATE PROCEDURE test
AS
BEGIN
END!
-- Statement failed, SQLSTATE = 42000
-- exception 1
-- -E_INVALID_SP_NAME
-- -Mauvais nom de la procédure stockée (devrait commencer par SP_)
-- -At trigger 'TRIG_DDL_SP' line: 4, col: 5
SET TERM ;!
Example 2. Opérateurs de contrôle de sécurité DDL
CREATE EXCEPTION e_access_denied 'Access denied';

SET TERM !;

CREATE TRIGGER trig_ddl BEFORE ANY DDL STATEMENT
AS
BEGIN
  IF (current_user <> 'SUPER_USER') THEN
    EXCEPTION e_access_denied;
END!

-- Test
CREATE PROCEDURE sp_test
AS
BEGIN
END!
-- The last command raises this exception and procedure SP_TEST is not created
-- Statement failed, SQLSTATE = 42000
-- exception 1
-- -E_ACCESS_DENIED
-- -Access denied
-- -At trigger 'TRIG_DDL' line: 4, col: 5
SET TERM ;!
Note

Dans Firebird, il existe des privilèges pour les opérateurs DDL, vous devez donc recourir à l’écriture d’un déclencheur DDL uniquement si le même effet ne peut pas être réalisé avec des méthodes standard.

Example 3. Utilisation de déclencheurs DDL pour enregistrer les modifications des métadonnées
CREATE SEQUENCE ddl_seq;

CREATE TABLE ddl_log (
  id BIGINT NOT NULL PRIMARY KEY,
  moment TIMESTAMP NOT NULL,
  user_name VARCHAR(63) NOT NULL,
  event_type VARCHAR(25) NOT NULL,
  object_type VARCHAR(25) NOT NULL,
  ddl_event VARCHAR(25) NOT NULL,
  object_name VARCHAR(63) NOT NULL,
  old_object_name VARCHAR(63),
  new_object_name VARCHAR(63),
  sql_text BLOB sub_type text NOT NULL,
  ok CHAR(1) NOT NULL
);

SET TERM !;

CREATE TRIGGER trig_ddl_log_before BEFORE ANY DDL STATEMENT
AS
  DECLARE id TYPE OF COLUMN ddl_log.id;
BEGIN
  -- Nous devons apporter des changements à la TRANSACTION AUTONOME,
  -- de cette façon, si une exception se produit et que la commande
  -- n'est pas exécutée, elle sera quand même enregistrée.
  IN AUTONOMOUS TRANSACTION DO
  BEGIN
    INSERT INTO ddl_log (
      id, moment, user_name, event_type, object_type, ddl_event,
      object_name, old_object_name, new_object_name, sql_text, ok)
    VALUES (NEXT VALUE FOR ddl_seq,
            current_timestamp, current_user,
            rdb$get_context('DDL_TRIGGER', 'EVENT_TYPE'),
            rdb$get_context('DDL_TRIGGER', 'OBJECT_TYPE'),
            rdb$get_context('DDL_TRIGGER', 'DDL_EVENT'),
            rdb$get_context('DDL_TRIGGER', 'OBJECT_NAME'),
            rdb$get_context('DDL_TRIGGER', 'OLD_OBJECT_NAME'),
            rdb$get_context('DDL_TRIGGER', 'NEW_OBJECT_NAME'),
            rdb$get_context('DDL_TRIGGER', 'SQL_TEXT'),
            'N')
    RETURNING id INTO id;
    rdb$set_context('USER_SESSION', 'trig_ddl_log_id', id);
  END
END!

-- Note :
-- Le déclencheur créé ci-dessus sera exécuté pour cette DDL.
-- Une bonne idée est d'utiliser -nodbtriggers
-- quand on travaille avec lui
CREATE TRIGGER trig_ddl_log_after AFTER ANY DDL STATEMENT
AS
BEGIN
  -- Dans ce cas, nous avons besoin d'une transaction autonome,
  -- parce que dans la transaction originale
  -- nous ne verrons pas l'enregistrement inséré dans la base de données
  -- AVANT le déclenchement d'une transaction hors ligne,
  -- si la transaction de l'utilisateur n'est pas lancée
  -- avec le mode d'isolation READ COMMITTED.
  IN AUTONOMOUS TRANSACTION DO
    UPDATE ddl_log SET ok = 'Y'
    WHERE
      id = rdb$get_context('USER_SESSION', 'trig_ddl_log_id');
END!

COMMIT!

SET TERM ;!

-- Nous supprimons l'enregistrement de la création trig_ddl_log_after.

DELETE FROM ddl_log;
COMMIT;

-- Test

-- Cette commande sera enregistrée une fois
-- (puisque T1 n'existe pas, RECREATE déclenchera l'événement CREATE)
-- avec OK = Y.

RECREATE TABLE t1 (
  n1 INTEGER,
  n2 INTEGER
);

-- L'opérateur ne s'exécutera pas car T1 existe déjà,
-- donc OK aura une valeur de N.

CREATE TABLE t1 (
  n1 INTEGER,
  n2 INTEGER
);

-- T2 n'existe pas. Cette action ne sera pas enregistrée.

DROP TABLE t2;

-- Cette action sera enregistrée deux fois
-- (puisque T1 existe, l'action RECREATE est traitée
-- comme DROP et CREATE) avec le champ OK = Y.

RECREATE TABLE t1 (
  n INTEGER
);

CREATE DOMAIN dom1 AS INTEGER;

ALTER DOMAIN dom1 TYPE BIGINT;

ALTER DOMAIN dom1 TO dom2;

COMMIT;

SELECT
  id,
  ddl_event,
  object_name as name,
  sql_text,
  ok
FROM ddl_log
ORDER BY id;
 ID DDL_EVENT                 OBJECT_NAME                      SQL_TEXT OK
=== ========================= ======================= ================= ======
  2 CREATE TABLE              T1                                   80:3 Y
====================================================
SQL_TEXT:
recreate table t1 (
    n1 integer,
    n2 integer
)
====================================================
  3 CREATE TABLE              T1                                   80:2 N
====================================================
SQL_TEXT:
create table t1 (
    n1 integer,
    n2 integer
)
====================================================
  4 DROP TABLE                T1                                   80:6 Y
====================================================
SQL_TEXT:
recreate table t1 (
    n integer
)
====================================================
  5 CREATE TABLE              T1                                   80:9 Y
====================================================
SQL_TEXT:
recreate table t1 (
    n integer
)
====================================================
Voir aussi :

ALTER TRIGGER, DROP TRIGGER.

ALTER TRIGGER

Utilisé pour:

Modification d’un déclencheur existant.

Disponible en

DSQL, ESQL

Syntaxe
ALTER TRIGGER trigname
[ACTIVE | INACTIVE]
[{BEFORE | AFTER} <mutation_list>]
[POSITION number]
[SQL SECURITY {DEFINER | INVOKER} | DROP SQL SECURITY]
[<routine-body>]

<mutation_list> ::= <mutation> [OR <mutation> [OR <mutation>]]

<mutation> ::= { INSERT | UPDATE | DELETE }

Description complète de l'opérateur Voir. CREATE TRIGGER.

Modifications autorisées

La déclaration de changement de déclencheur peut être modifiée :

  • Etat de l’activité (ACTIVE | INACTIVE) ;

  • Phase (BEFORE | AFTER) ;

  • Événement(s) ;

  • Position de la commande ;

  • Privilèges d’exécution des déclencheurs : appeler l’utilisateur (SQL SECURITY INVOKER), définir l’utilisateur (SQL SECURITY DEFINER) ou hériter de la table (DROP SQL SECURITY) ;

  • Code du corps du déclencheur.

Si un élément n’est pas spécifié, il reste inchangé.

Note

Un déclencheur DML ne peut pas être transformé en un déclencheur d’événement de base de données et vice versa.

Un événement dans un déclencheur de base de données ne peut pas être modifié.

Tip
N’oubliez pas

Le déclencheur avec le mot clé BEFORE vient avant l’événement correspondant, avec le mot clé AFTER vient après l’événement correspondant.

Un déclencheur DML peut contenir plus d’un événement (INSERT, UPDATE, DELETE). Les événements doivent être séparés par le mot clé OR.Chacun des événements ne peut être spécifié plus d’une fois.

Le mot clé POSITIONALTER TRIGGER, POSITION permet de spécifier un ordre d’exécution supplémentaire avec la même phase et le même événement.Par défaut, la position est 0.Si aucune position n’est spécifiée, ou si plusieurs déclencheurs ont le même numéro de position, les déclencheurs seront exécutés dans l’ordre alphabétique de leur nom.

Qui peut changer les déclencheurs ?

Les déclencheurs DML peuvent changer :

  • Administrateurs.

  • Propriétaire de la table (vue) ;

  • Les utilisateurs ayant le privilège `ALTER ANY {TABLE | VIEW}'.

Les déclencheurs pour les événements de la base de données et les déclencheurs d’événements pour les changements de métadonnées peuvent changer :

  • Administrateurs.

  • Propriétaire de la base de données ;

  • Un utilisateur avec le privilège `ALTER DATABASE'.

Exemples

Example 1. Désactiver (mettre inactif) le déclencheur
ALTER TRIGGER set_cust_no INACTIVE;
Example 2. Changer la position du déclencheur
ALTER TRIGGER set_cust_no POSITION 14;
Example 3. Mettre le déclencheur dans un état inactif et modifier la liste des événements
ALTER TRIGGER TR_CUST_LOG
INACTIVE AFTER INSERT OR UPDATE;
Example 4. Modification des privilèges d’exécution des déclencheurs

Une fois cette instruction exécutée, le déclencheur sera exécuté avec les privilèges de l’utilisateur qui le définit (propriétaire).

ALTER TRIGGER TR_CUST_LOG
SQL SECURITY DEFINER;
Example 5. Suppression des privilèges d’exécution des déclencheurs

Après avoir supprimé les privilèges d’exécution du déclencheur, celui-ci sera exécuté avec les privilèges hérités de la table.Si la table n’a pas de privilèges d’exécution définis, le déclencheur sera exécuté avec les privilèges de l’utilisateur appelant.

ALTER TRIGGER TR_CUST_LOG
DROP SQL SECURITY;
Example 6. Faire passer le déclencheur à l’état actif, en modifiant sa position et son corps.
ALTER TRIGGER tr_log_connect
ACTIVE POSITION 1
AS
BEGIN
  INSERT INTO LOG_CONNECT (ID,
                           USERNAME,
                           ROLENAME,
                           ATIME)
  VALUES (NEXT VALUE FOR SEQ_LOG_CONNECT,
          CURRENT_USER,
          CURRENT_ROLE,
          CURRENT_TIMESTAMP);
END

CREATE OR ALTER TRIGGER

Utilisé pour:

Créez un nouveau déclencheur ou modifiez un déclencheur existant.

Disponible en

DSQL, ESQL

Syntaxe
CREATE OR ALTER TRIGGER trigname {
    <relation_trigger_legacy>
  | <relation_trigger_sql2003>
  | <database_trigger>
  | <ddl_trigger> }
<routine-body>

Pour une description complète de l'opérateur, voir CREATE TRIGGER.

L’instruction CREATE OR ALTER TRIGGER crée un nouveau trigger s’il n’existe pas, ou le modifie et le recompile sinon, avec les droits et dépendances existants préservés.

Exemples

Example 1. Création d’un nouveau déclencheur ou modification d’un déclencheur existant
CREATE OR ALTER TRIGGER set_cust_no
ACTIVE BEFORE INSERT ON customer POSITION 0
AS
BEGIN
  IF (NEW.cust_no IS NULL) THEN
    NEW.cust_no = GEN_ID(cust_no_gen, 1);
END

DROP TRIGGER

Utilisé pour:

Suppression d’un déclencheur existant.

Disponible en

DSQL, ESQL

Syntaxe
DROP TRIGGER trigname
Table 1. Paramètres de la commande DROP TRIGGER
Paramètre Description

trigname

Nom du déclencheur.

L’instruction `DROP TRIGGER' supprime un trigger existant.

Qui peut supprimer les déclencheurs ?

Les déclencheurs DML peuvent supprimer :

  • Administrateurs.

  • Propriétaire de la table (vue) ;

  • Les utilisateurs ayant le privilège `ALTER ANY {TABLE | VIEW}'.

Les déclencheurs pour les événements de la base de données et les déclencheurs d’événements pour les changements de métadonnées peuvent être supprimés :

  • Administrateurs.

  • Propriétaire de la base de données ;

  • Un utilisateur avec le privilège `ALTER DATABASE'.

Exemples

Example 1. Supprimer le Trigger
DROP TRIGGER set_cust_no;
Voir aussi :

CREATE TRIGGER, ALTER TRIGGER.

RECREATE TRIGGER

Utilisé pour:

Créez un nouveau déclencheur ou recréez un déclencheur existant.

Disponible en

DSQL, ESQL

Syntaxe
RECREATE TRIGGER trigname {
    <relation_trigger_legacy>
  | <relation_trigger_sql2003>
  | <database_trigger>
  | <ddl_trigger> }
<routine-body>

Description complète de l'opérateur Voir CREATE TRIGGER.

L’opérateur RECREATE TRIGGER crée un nouveau trigger si le trigger avec le nom spécifié n’existe pas, sinon l’opérateur RECREATE TRIGGER essaiera de le supprimer et d’en créer un nouveau.

Exemples

Example 1. Créer ou recréer un trigger
RECREATE TRIGGER set_cust_no
ACTIVE BEFORE INSERT ON customer POSITION 0
AS
BEGIN
  IF (NEW.cust_no IS NULL) THEN
    NEW.cust_no = GEN_ID(cust_no_gen, 1);
END