Wer kann einen DDL-Trigger erstellen?
DDL-Trigger können erstellt werden durch:
- 
Benutzer mit dem ALTER DATABASE-Privileg
DDL-Trigger können erstellt werden durch:
Benutzer mit dem ALTER DATABASE-Privileg
Ein DDL-Trigger ist eine Art Datenbank-Trigger.Siehe auch [fblangref40-ddl-trgr-dbtrigger-notrgr-de] wie man Datenbank- und DDL-Trigger unterdrückt.
So können Sie einen DDL-Trigger verwenden, um ein konsistentes Benennungsschema zu erzwingen. In diesem Fall sollten die Namen der gespeicherten Prozeduren mit dem Präfix “SP_” beginnen:
set auto on;
create exception e_invalid_sp_name 'Invalid SP name (should start with 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!
-- Der letzte Befehl löst diese Ausnahme aus und die Prozedur TEST wird nicht erstellt:
-- Statement failed, SQLSTATE = 42000
-- exception 1
-- -E_INVALID_SP_NAME
-- -Invalid SP name (should start with SP_)
-- -At trigger 'TRIG_DDL_SP' line: 4, col: 5
set term ;!Implementieren Sie benutzerdefinierte DDL-Sicherheit, indem Sie in diesem Fall die Ausführung von DDL-Befehlen auf bestimmte Benutzer beschränken:
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!
-- Der letzte Befehl löst diese Ausnahme aus und die Prozedur SP_TEST wird nicht erstellt
-- Statement failed, SQLSTATE = 42000
-- exception 1
-- -E_ACCESS_DENIED
-- -Access denied
-- -At trigger 'TRIG_DDL' line: 4, col: 5
set term ;!| Note | Firebird hat Berechtigungen zum Ausführen von DDL-Anweisungen, daher sollte das Schreiben eines DDL-Triggers dafür der letzte Ausweg sein, wenn der gleiche Effekt nicht mit Berechtigungen erzielt werden kann. | 
Verwenden eines Triggers, um DDL-Aktionen und -Versuche zu protokollieren:
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,
  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
  -- Wir nehmen die Änderungen in einer AUTONOMEN TRANSAKTION vor. Wenn also eine Ausnahme auftritt und
  -- der Befehl nicht ausgeführt wurde, bleibt das Protokoll erhalten.
  in autonomous transaction do
  begin
    insert into ddl_log (id, moment, user_name, event_type, object_type,
                         ddl_event, 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', 'SQL_TEXT'),
              'N')
      returning id into id;
    rdb$set_context('USER_SESSION', 'trig_ddl_log_id', id);
  end
end!Der obige Trigger wird für diesen DDL-Befehl ausgelöst.Es ist eine gute Idee, -nodbtriggers zu verwenden, wenn Sie mit ihnen arbeiten!
create trigger trig_ddl_log_after after any ddl statement
as
begin
  -- Hier benötigen wir eine AUTONOME TRANSACTION, da die ursprüngliche Transaktion den Datensatz
  -- nicht sehen wird, der in den BEFORE-Trigger der
  -- autonomen Transaktion eingefügt wurde, wenn die Benutzertransaktion nicht READ COMMITTED ist.
  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 ;!
-- Löschen Sie den Datensatz über trig_ddl_log_after
delete from ddl_log;
commit;Test
-- Dies wird einmalig protokolliert
-- (da T1 nicht existierte, fungiert RECREATE als CREATE) mit OK = Y.
recreate table t1 (
  n1 integer,
  n2 integer
);
-- Dies schlägt fehl, da T1 bereits existiert, also ist OK N.
create table t1 (
  n1 integer,
  n2 integer
);
-- T2 existiert nicht. Es wird kein Protokoll geben.
drop table t2;
-- Dies wird zweimal protokolliert
-- (da T1 existiert, fungiert RECREATE als DROP und CREATE) mit OK = Y.
recreate table t1 (
  n integer
);
commit;select id, ddl_event, object_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
)
====================================================[fblangref40-ddl-trgr-alter-de], [fblangref40-ddl-trgr-crtalter-de], [fblangref40-ddl-trgr-recreate-de], [fblangref40-ddl-trgr-drop-de], DDL-Trigger im Kapitel Procedural SQL (PSQL)-Anweisungen
ALTER TRIGGERÄndern und Deaktivieren eines bestehenden Triggers
DSQL, ESQL
ALTER TRIGGER trigname
  [ACTIVE | INACTIVE]
  [{BEFORE | AFTER} <mutation_list>]
  [POSITION number]
  {<psql_trigger> | <external-module-body>}
<psql_trigger> ::=
  [<sql_security>]
  [<psql-module-body>]
<sql_security> ::=
    SQL SECURITY {INVOKER | DEFINER}
  | DROP SQL SECURITY
!! Vgl. auch die Syntax CREATE TRIGGER für weitere Regeln!!
Die ALTER TRIGGER-Anweisung erlaubt nur bestimmte Änderungen am Header und Body eines Triggers.
Status (ACTIVE | INACTIVE)
Phase (BEFORE | AFTER) (bei DML-Triggern)
Ereignisse (bei DML-Triggern)
Position in der Ausführungsfolge
Änderungen am Code im Trigger-Body
Wenn ein Element nicht angegeben wird, bleibt es unverändert.
| Note | Ein DML-Trigger kann nicht in einen Datenbank- (oder DDL-)Trigger geändert werden. Es ist nicht möglich, das/die Ereignis(e) oder die Phase eines Datenbank- (oder DDL-)Triggers zu ändern. | 
| Note | Merken Sie sich Das Schlüsselwort  Mehrere DML-Ereignisse –  Das Schlüsselwort  | 
DML-Trigger können geändert werden durch:
Der Besitzer der Tabelle (oder Ansicht)
Benutzer mit dem ALTER ANY TABLE- oder — für eine Ansicht — ALTER ANY VIEW-Privileg
Datenbank- und DDL-Trigger können geändert werden durch:
Benutzer mit dem ALTER DATABASE-Privileg
Den Trigger set_cust_no deaktivieren (in den inaktiven Zustand schalten).
ALTER TRIGGER set_cust_no INACTIVE;Ändern der Position der Zündreihenfolge des Triggers set_cust_no.
ALTER TRIGGER set_cust_no POSITION 14;Den Trigger TR_CUST_LOG in den inaktiven Zustand schalten und die Ereignisliste ändern.
ALTER TRIGGER TR_CUST_LOG
INACTIVE AFTER INSERT OR UPDATE;Den tr_log_connect Trigger in den aktiven Status schalten, seine Position und seinen Körper ändern.
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);
ENDCREATE OR ALTER TRIGGERErstellen eines neuen Triggers oder Ändern eines bestehenden Triggers
DSQL
CREATE OR ALTER TRIGGER trigname
  { <relation_trigger_legacy>
  | <relation_trigger_sql2003>
  | <database_trigger>
  | <ddl_trigger> }
  {<psql_trigger> | <external-module-body>}
!!Vgl. auch die Syntax CREATE TRIGGER für weitere Regeln !!
Die Anweisung CREATE OR ALTER TRIGGER erstellt einen neuen Trigger, falls dieser nicht existiert;andernfalls ändert und kompiliert es sie mit den intakten Privilegien und unberührten Abhängigkeiten.
CREATE OR ALTER TRIGGERCREATE 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);
ENDDROP TRIGGERLöschen eines vorhandenen Triggers
DSQL, ESQL
DROP TRIGGER trigname
| Parameter | Beschreibung | 
|---|---|
| trigname | Triggername | 
Die Anweisung DROP TRIGGER verwirft (löscht) einen vorhandenen Trigger.
DML-Trigger können gelöscht werden durch:
Der Besitzer der Tabelle (oder Ansicht)
Benutzer mit dem ALTER ANY TABLE- oder — für eine Ansicht — ALTER ANY VIEW-Privileg
Datenbank- und DDL-Trigger können gelöscht werden durch:
Benutzer mit dem ALTER DATABASE-Privileg
DROP TRIGGERset_cust_noDROP TRIGGER set_cust_no;RECREATE TRIGGERErstellen eines neuen Triggers oder Neuerstellen eines vorhandenen Triggers
DSQL
RECREATE TRIGGER trigname
  { <relation_trigger_legacy>
  | <relation_trigger_sql2003>
  | <database_trigger>
  | <ddl_trigger> }
  {<psql_trigger> | <external-module-body>}
!! Vgl. auch die Syntax CREATE TRIGGER für weitere Regeln !!
Die Anweisung RECREATE TRIGGER erstellt einen neuen Trigger, wenn kein Trigger mit dem angegebenen Namen existiert;andernfalls versucht die Anweisung RECREATE TRIGGER, den vorhandenen Trigger zu löschen und einen neuen zu erstellen.Die Operation schlägt bei COMMIT fehl, wenn der Trigger verwendet wird.
| Warning | Beachten Sie, dass Abhängigkeitsfehler erst in der  | 
RECREATE TRIGGERErstellen oder erneutes Erstellen des Triggers set_cust_no.
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