Unterdrücken von DDL-Triggern
Ein DDL-Trigger ist eine Art Datenbank-Trigger.Siehe auch [fblangref40-ddl-trgr-dbtrigger-notrgr-de] wie man Datenbank- und DDL-Trigger unterdrückt.
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);
END
CREATE OR ALTER TRIGGER
Erstellen 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 TRIGGER
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
Lö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 TRIGGER
set_cust_no
DROP TRIGGER set_cust_no;
RECREATE TRIGGER
Erstellen 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 TRIGGER
Erstellen 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