Wir können DDL in keiner Form von PL/SQL nativ ausführen. inklusive Auslöser. Dazu müssen wir dynamisches SQL verwenden.
Trigger haben einen zusätzlichen Haken:Sie werden als Teil der Transaktion ausgelöst, und sie haben eine Einschränkung, die es uns verbietet, einen Commit in ihrem Körper auszugeben. In Oracle gibt jeder DDL-Befehl zwei Commits aus, einen vor und einen nach der Ausführung der DDL-Anweisung. Um also DDL in einem Trigger auszuführen, müssen wir das Pragma autonomous_transaction pragma
verwenden , was bedeutet, dass die DDL in einer separaten, verschachtelten Transaktion ausgeführt wird.
create or replace TRIGGER TestTrigger
BEFORE INSERT ON TestTable
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
declare
pragma autonomous_transaction;
BEGIN
execute immediate 'create role '|| :New.RoleName;
END;
Autonome Transaktionen sind eines dieser Konstrukte, die für uns leicht zu missbrauchen und unsere eigenen Anwendungen zu sabotieren sind. In Ihrem Szenario besteht der Haken darin, dass die CREATE ROLE in ihrer Transaktionsblase erfolgreich sein kann, während die INSERTT in TestTable
scheitert; dies ist die Bedeutung von "autonome Transaktion". Sie haben also immer noch keine Garantie für "Kohärenz zwischen [Ihrer] Tabelle und Orakelrollen eins".
Eine bessere Lösung wäre, beide Anweisungen in einen prozeduralen Aufruf zu verpacken, anstatt zu versuchen, DML dazu zu bringen, etwas zu tun, was es nicht tun soll.
create or replace procedure create_role
( p_role_name in user_roles.role%type
, p_desc in testtable.description%type )
is
pragma autonomous_transaction;
begin
insert into testtable
( id, creationdate, rolename, description)
values
( some_seq.nextval, sysdate, p_role_name, p_desc );
execute immediate 'create role '|| p_role_name;
end;