Oracle
 sql >> Base de données >  >> RDS >> Oracle

Oracle :Est-il possible de créer un Rôle dans un Trigger ?

Nous ne pouvons pas exécuter nativement DDL sous aucune forme de PL/SQL. y compris les déclencheurs. Pour ce faire, nous devons utiliser SQL dynamique.

Les déclencheurs ont un inconvénient supplémentaire :ils sont déclenchés dans le cadre de la transaction et ils ont une limitation qui nous interdit d'émettre un commit à l'intérieur de leur corps. Dans Oracle, toute commande DDL émet deux commits, un avant et un après l'exécution de l'instruction DDL. Ainsi, pour exécuter DDL dans un déclencheur, nous devons utiliser le pragma autonomous_transaction pragma , ce qui signifie que le DDL s'exécute dans une transaction imbriquée distincte.

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;

Les transactions autonomes sont l'une de ces constructions qui nous permettent facilement d'abuser et de saboter nos propres applications. Dans votre scénario, le hic est que le CREATE ROLE peut réussir dans sa bulle de transaction tandis que l'INSERTT dans TestTable échoue; tel est le sens de "transaction autonome". Vous n'êtes donc toujours pas assuré "de la cohérence entre [votre] table et les rôles oracle un".

Une meilleure solution serait de regrouper les deux instructions dans un appel procédural, plutôt que d'essayer de tromper DML pour qu'il fasse quelque chose qu'il n'est pas censé faire.

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;