2010-08-16 7 views
3

Je ne sais pas si c'est correct, mais pour une raison quelconque, ma procédure stockée ne recule pas après une exception. Donc, mon instruction d'insertion est validée même lorsque je reçois une exceptionProcédure de restauration @ stockée sur Oracle

J'ai oublié quelque chose?

PROCEDURE SP_USUARIO_INSERT 
     (
      pUSU_IDUSUARIO   IN OUT ENG.USU_USUARIO.USU_IDUSUARIO%TYPE, 
      pUSU_CDUSUARIO   IN ENG.USU_USUARIO.USU_CDUSUARIO%TYPE, 
      pPES_IDPESSOA   IN ENG.USU_USUARIO.PES_IDPESSOA%TYPE, 
      pUSU_DLSENHA   IN ENG.USU_USUARIO.USU_CDUSUARIO%TYPE, 
      pUSU_DLOBSERVACAO  IN ENG.USU_USUARIO.USU_DLOBSERVACAO%TYPE, 
      pUSU_NUIP    IN ENG.USU_USUARIO.USU_NUIP%TYPE, 
      pUSU_DTCADASTRO   IN ENG.USU_USUARIO.USU_DTCADASTRO%TYPE, 
      pUSU_DTDESATIVACAO  IN ENG.USU_USUARIO.USU_DTDESATIVACAO%TYPE, 
      pUSU_DTULTIMOACESSO  IN ENG.USU_USUARIO.USU_DTULTIMOACESSO%TYPE, 
      pUSU_DLMAQUINA   IN ENG.USU_USUARIO.USU_DLMAQUINA%TYPE, 
      pUSU_STNOVO    IN ENG.USU_USUARIO.USU_STNOVO%TYPE, 
      pUSU_STATIVO   IN ENG.USU_USUARIO.USU_STATIVO%TYPE 
     ) 
IS 
sCreateUser Varchar(200); 
bUsuarioExiste Number; 
eUsuarioExiste Exception; 
BEGIN 
     SELECT 
       COUNT(usu_cdusuario) 
       INTO bUsuarioExiste 
     FROM ENG.USU_USUARIO 
     WHERE USU_CDUSUARIO = pUSU_CDUSUARIO; 

     IF(bUsuarioExiste > 0) THEN 
       RAISE eUsuarioExiste; 
     END IF; 

     SELECT usu_seq.nextval INTO pUSU_IDUSUARIO FROM DUAL; 

     INSERT INTO ENG.USU_USUARIO 
      (
       USU_IDUSUARIO, 
       USU_CDUSUARIO, 
       PES_IDPESSOA, 
       USU_DLOBSERVACAO, 
       USU_NUIP, 
       USU_DTCADASTRO, 
       USU_DTDESATIVACAO, 
       USU_DTULTIMOACESSO, 
       USU_DLMAQUINA, 
       USU_STNOVO, 
       USU_STATIVO 
      ) 
     VALUES 
      (
       pUSU_IDUSUARIO, 
       pUSU_CDUSUARIO, 
       pPES_IDPESSOA, 
       pUSU_DLOBSERVACAO, 
       pUSU_NUIP, 
       sysdate, 
       pUSU_DTDESATIVACAO, 
       pUSU_DTULTIMOACESSO, 
       pUSU_DLMAQUINA, 
       pUSU_STNOVO, 
       pUSU_STATIVO 
      ) ; 
     sCreateUser := 'CREATE USER ' || pUSU_CDUSUARIO || ' IDENTIFIED BY ' || pUSU_DLSENHA; 
     EXECUTE IMMEDIATE sCreateUser; 
     EXECUTE IMMEDIATE 'GRANT ENG_GERAL TO ' || pUSU_CDUSUARIO; 
     COMMIT; 
EXCEPTION 
     WHEN eUsuarioExiste THEN 
      RAISE_APPLICATION_ERROR (-20001, 'Usuário já existe ou possui nome inválido.'); 
      ROLLBACK; 
     WHEN OTHERS THEN 
      RAISE_APPLICATION_ERROR (-20001, SQLCODE || ': ' || SQLERRM); 
      ROLLBACK; 
END SP_USUARIO_INSERT; 
+2

Difficile à dire sans voir votre code –

+0

peut-être un commit est exécuté lorsque le SP se termine? S'il vous plaît poster du code. Un court extrait décrivant le problème est OK. – Tom

+2

Votre procédure stockée effectue-t-elle un DDL? Cela impliquera implicitement toutes les instructions DML en attente. Cependant, sans code, tout ce que nous faisons est de deviner. –

Répondre

1

Je suppose que vous «gérez» (ou plus exactement, en ignorant) votre exception.

create table temp (id number); 
DECLARE 
    v_str VARCHAR2(2); 
BEGIN 
    INSERT INTO temp VALUES (1); 
    v_str := '123'; 
EXCEPTION 
    WHEN VALUE_ERROR THEN DBMS_OUTPUT.PUT_LINE('Whoops'); 
END; 
/
select * from temp; 

Montrera la ligne parce que, dans la mesure où la couche SQL est concernée, la procédure terminée avec succès (comme l'exception a été capturé et ignoré).

Il peut y avoir d'autres raisons telles que

  • L'insert se produit avant l'exécution de la procédure et ainsi ne sera pas annulée en cas d'échec de la déclaration (et que vous ne rollback explicitement la transaction)
  • Le L'insertion est validée par une validation explicite avant que l'exception ne soit déclenchée.
+0

Theres un moyen de revenir en arrière? – alex

5

La commande "EXECUTE IMMEDIATE sCreateUser;" est implicitement en train de valider votre insertion.

+0

Très bien, réparé d'une autre façon, merci les gars. – alex

0

Je pense que si vous restructurez votre code, vous pouvez obtenir le comportement que vous voulez.

PROCEDURE SP_USUARIO_INSERT  
     (  
      pUSU_IDUSUARIO   IN OUT ENG.USU_USUARIO.USU_IDUSUARIO%TYPE,  
      pUSU_CDUSUARIO   IN ENG.USU_USUARIO.USU_CDUSUARIO%TYPE,  
      pPES_IDPESSOA   IN ENG.USU_USUARIO.PES_IDPESSOA%TYPE,  
      pUSU_DLSENHA   IN ENG.USU_USUARIO.USU_CDUSUARIO%TYPE,  
      pUSU_DLOBSERVACAO  IN ENG.USU_USUARIO.USU_DLOBSERVACAO%TYPE,  
      pUSU_NUIP    IN ENG.USU_USUARIO.USU_NUIP%TYPE,  
      pUSU_DTCADASTRO   IN ENG.USU_USUARIO.USU_DTCADASTRO%TYPE,  
      pUSU_DTDESATIVACAO  IN ENG.USU_USUARIO.USU_DTDESATIVACAO%TYPE,  
      pUSU_DTULTIMOACESSO  IN ENG.USU_USUARIO.USU_DTULTIMOACESSO%TYPE,  
      pUSU_DLMAQUINA   IN ENG.USU_USUARIO.USU_DLMAQUINA%TYPE,  
      pUSU_STNOVO    IN ENG.USU_USUARIO.USU_STNOVO%TYPE,  
      pUSU_STATIVO   IN ENG.USU_USUARIO.USU_STATIVO%TYPE  
     )  
IS  
sCreateUser Varchar(200);  
bUsuarioExiste Number;  
eUsuarioExiste Exception;  
l_sqlcode  number; 
BEGIN  
     SELECT  
       COUNT(usu_cdusuario)  
       INTO bUsuarioExiste  
     FROM ENG.USU_USUARIO  
     WHERE USU_CDUSUARIO = pUSU_CDUSUARIO;  

     IF(bUsuarioExiste > 0) THEN  
       RAISE eUsuarioExiste;  
     END IF;  

     sCreateUser := 'CREATE USER ' || pUSU_CDUSUARIO || ' IDENTIFIED BY ' ||  
         pUSU_DLSENHA;  
     EXECUTE IMMEDIATE sCreateUser;  

     begin 
       EXECUTE IMMEDIATE 'GRANT ENG_GERAL TO ' || pUSU_CDUSUARIO;  

       -- moved this into the insert   
       --SELECT usu_seq.nextval INTO pUSU_IDUSUARIO FROM DUAL;  

       INSERT INTO ENG.USU_USUARIO  
       (  
        USU_IDUSUARIO,  
        USU_CDUSUARIO,  
        PES_IDPESSOA,  
        USU_DLOBSERVACAO,  
        USU_NUIP,  
        USU_DTCADASTRO,  
        USU_DTDESATIVACAO,  
        USU_DTULTIMOACESSO,  
        USU_DLMAQUINA,  
        USU_STNOVO,  
        USU_STATIVO  
      )  
       VALUES  
       (  
        usu_seq.nextval, --pUSU_IDUSUARIO,  
        pUSU_CDUSUARIO,  
        pPES_IDPESSOA,  
        pUSU_DLOBSERVACAO,  
        pUSU_NUIP,  
        sysdate,  
        pUSU_DTDESATIVACAO,  
        pUSU_DTULTIMOACESSO,  
        pUSU_DLMAQUINA,  
        pUSU_STNOVO,  
        pUSU_STATIVO  
      ) 
       returning ;  
     exception 
      when others then 
      -- save off the sqlcode, you will need it to reraise 
      l_sqlcode := SQLCODE; 
      -- rollback any insert that may have run, 
      -- depending on where the exception was raised 
      rollback; 
      -- drop the created user 
      execute immediate 'drop user ' || pUSU_CDUSUARIO ; 
      -- reraise the error 
      RAISE_APPLICATION_ERROR (-20001, l_sqlcode || ': ' || 
             SQLERRM(-l_sqlcode));     
     end; 

     COMMIT;  
EXCEPTION  
     WHEN eUsuarioExiste THEN  
      RAISE_APPLICATION_ERROR (-20001, 
         'Usuário já existe ou possui nome inválido.');  
      ROLLBACK;  
     WHEN OTHERS THEN  
      RAISE_APPLICATION_ERROR (-20001, 
       SQLCODE || ': ' || SQLERRM);  
      ROLLBACK;  
END SP_USUARIO_INSERT; 
0

ne pas le RAISE_APPLICATION_ERROR signifie que le ROLLBACK est injoignable? À moins que l'appelant n'émette aussi un ROLLBACK, je pense que ce doit être l'inverse. Vous avez peut-être un engagement implicite de DDL, comme d'autres l'ont dit, en fonction de ce qui est réellement erroné, donc cela peut ne pas être pertinent, mais cela ne semble pas tout à fait correct.

Questions connexes