Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Oracle:É possível criar um Role em um Trigger?


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;