Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Oracle :Ist es möglich, eine Rolle in einem Trigger zu erstellen?

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;