No podemos ejecutar DDL de forma nativa en ninguna forma de PL/SQL. incluyendo disparadores. Para hacer eso, necesitamos usar SQL dinámico.
Los disparadores tienen una característica adicional:se activan como parte de la transacción y tienen una limitación que nos prohíbe emitir una confirmación dentro de su cuerpo. En Oracle, cualquier comando DDL emite dos confirmaciones, una antes y otra después de ejecutar la instrucción DDL. Entonces, para ejecutar DDL en un disparador, debemos usar el autonomous_transaction pragma
, lo que significa que el DDL se ejecuta en una transacción anidada separada.
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;
Las transacciones autónomas son una de esas construcciones que es fácil para nosotros maltratar y sabotear nuestras propias aplicaciones. En su escenario, el inconveniente es que CREATE ROLE puede tener éxito en su burbuja de transacción mientras que INSERTT en TestTable
falla; tal es el significado de "transacción autónoma". Por lo tanto, aún no tiene garantizada la "coherencia entre [su] tabla y los roles de oráculo uno".
Una mejor solución sería envolver ambas declaraciones en una llamada de procedimiento, en lugar de intentar engañar a DML para que haga algo que se supone que no debe hacer.
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;