Oracle
 sql >> Database >  >> RDS >> Oracle

Oracle:è possibile creare un ruolo in un trigger?

Non possiamo eseguire nativamente DDL in nessuna forma di PL/SQL. compresi i trigger. Per farlo abbiamo bisogno di usare SQL dinamico.

I trigger hanno un'ulteriore ruga:vengono attivati ​​​​come parte della transazione e hanno una limitazione che ci vieta di emettere un commit all'interno del loro corpo. In Oracle, qualsiasi comando DDL emette due commit, uno prima e uno dopo l'esecuzione dell'istruzione DDL. Quindi, per eseguire DDL in un trigger dobbiamo usare il autonomous_transaction pragma , il che significa che il DDL viene eseguito in una transazione nidificata separata.

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;

Le transazioni autonome sono uno di quei costrutti che sono facili da usare in modo improprio e sabotare le nostre stesse applicazioni. Nel tuo scenario l'inconveniente è che CREATE ROLE può avere successo nella sua bolla di transazione mentre INSERTT in TestTable non riesce; tale è il significato di "transazione autonoma". Quindi non ti è ancora garantita la "coerenza tra il [tuo] tavolo e i ruoli dell'oracolo uno".

Una soluzione migliore sarebbe racchiudere entrambe le istruzioni in una chiamata procedurale, piuttosto che tentare di indurre DML a fare qualcosa che non dovrebbe fare.

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;