Beispiele für DDL-Trigger
-
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 ;!
NoteFirebird 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