Não podemos executar DDL nativamente em nenhuma forma de PL/SQL. incluindo gatilhos. Para fazer isso, precisamos usar SQL dinâmico.
Os gatilhos têm um detalhe adicional:eles são disparados como parte da transação e têm uma limitação que nos proíbe de emitir um commit dentro de seu corpo. No Oracle, qualquer comando DDL emite dois commits, um antes e outro depois que a instrução DDL é executada. Então, para executar DDL em um trigger devemos usar o
autonomous_transaction pragma
, o que significa que o DDL é executado em uma transação aninhada 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;
A transação autônoma é uma daquelas construções que são fáceis para nós usarmos mal e sabotar nossos próprios aplicativos. No seu cenário, o problema é que o CREATE ROLE pode ter sucesso em sua bolha de transação enquanto o INSERTT em
TestTable
falha; tal é o significado de "transação autônoma". Portanto, você ainda não tem garantia de "coerência entre [sua] tabela e funções do oráculo um". Uma solução melhor seria envolver ambas as instruções em uma chamada procedural, em vez de tentar enganar o DML para fazer algo que não deveria fazer.
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;