2009-11-19 11 views
14

Możemy użyć RAISE, aby zwolnić wyjątek. Jakich szczególnych sytuacji potrzebujemy, aby użyć RAISE_APPLICATION_ERROR?Oracle: w jakiej sytuacji używać RAISE_APPLICATION_ERROR?

Dzięki.

+0

Znalazłem przydatny link dla podobnego pytania. http://www.toadworld.com/platforms/oracle/b/weblog/archive/2010/07/14/raise-vs-raise-application-error.aspx –

Odpowiedz

27

Istnieją dwa zastosowania RAISE_APPLICATION_ERROR. Pierwszym jest zastąpienie ogólnych komunikatów wyjątków Oracle naszymi własnymi, bardziej znaczącymi komunikatami. Druga polega na stworzeniu własnych wyjątków, gdy Oracle ich nie wyrzuci.

Poniższa procedura ilustruje oba zastosowania. Wymusza regułę biznesową, że nowych pracowników nie można zatrudnić w przyszłości. Zastępuje również dwa wyjątki Oracle. Jednym z nich jest DUP_VAL_ON_INDEX, który jest wyrzucany przez unikalny klucz na EMP(ENAME). Drugi to zdefiniowany przez użytkownika wyjątek generowany, gdy klucz obcy między EMP(MGR) i EMP(EMPNO) jest naruszony (ponieważ menedżer musi być istniejącym pracownikiem).

create or replace procedure new_emp 
    (p_name in emp.ename%type 
     , p_sal in emp.sal%type 
     , p_job in emp.job%type 
     , p_dept in emp.deptno%type 
     , p_mgr in emp.mgr%type 
     , p_hired in emp.hiredate%type := sysdate) 
is 
    invalid_manager exception; 
    PRAGMA EXCEPTION_INIT(invalid_manager, -2291); 
    dummy varchar2(1); 
begin 
    -- check hiredate is valid 
    if trunc(p_hired) > trunc(sysdate) 
    then 
     raise_application_error 
      (-20000 
      , 'NEW_EMP::hiredate cannot be in the future'); 
    end if; 

    insert into emp 
     (ename 
      , sal 
      , job 
      , deptno 
      , mgr 
      , hiredate) 
    values  
     (p_name 
      , p_sal 
      , p_job 
      , p_dept 
      , p_mgr 
      , trunc(p_hired)); 
exception 
    when dup_val_on_index then 
     raise_application_error 
      (-20001 
      , 'NEW_EMP::employee called '||p_name||' already exists' 
      , true); 
    when invalid_manager then 
     raise_application_error 
      (-20002 
      , 'NEW_EMP::'||p_mgr ||' is not a valid manager'); 

end; 
/

Jak to wygląda:

SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate+1) 
BEGIN new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate+1); END; 

* 
ERROR at line 1: 
ORA-20000: NEW_EMP::hiredate cannot be in the future 
ORA-06512: at "APC.NEW_EMP", line 16 
ORA-06512: at line 1 

SQL> 
SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 8888, sysdate) 
BEGIN new_emp ('DUGGAN', 2500, 'SALES', 10, 8888, sysdate); END; 

* 
ERROR at line 1: 
ORA-20002: NEW_EMP::8888 is not a valid manager 
ORA-06512: at "APC.NEW_EMP", line 42 
ORA-06512: at line 1 


SQL> 
SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate) 

PL/SQL procedure successfully completed. 

SQL> 
SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate) 
BEGIN new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate); END; 

* 
ERROR at line 1: 
ORA-20001: NEW_EMP::employee called DUGGAN already exists 
ORA-06512: at "APC.NEW_EMP", line 37 
ORA-00001: unique constraint (APC.EMP_UK) violated 
ORA-06512: at line 1 

Uwaga różne wyjścia z dwoma połączeniami do RAISE_APPLICATION_ERROR w wyjątków blokowania. Ustawienie opcjonalnego trzeciego argumentu na PRAWDA oznacza, że ​​RAISE_APPLICATION_ERROR zawiera wyjątek wyzwalający w stosie, który może być przydatny do diagnozy.

Istnieje więcej przydatnych informacji w the PL/SQL User's Guide.

1

jeśli twoja aplikacja akceptuje błędy podniesione z Oracle, możesz go użyć. mamy aplikację, za każdym razem, gdy wystąpi błąd, wywołujemy raise_application_error, aplikacja wyświetli czerwone pole, aby wyświetlić komunikat o błędzie, który przekazujemy za pomocą tej metody.

Używając kodu dotnetowego, używam tylko "podniesienia", wyjątek wyjątek dotnet automatycznie przechwyci błąd przekazany przez Oracle ODP i wyświetli się wewnątrz mojego kodu wyjątku catch.

3

Aby nieco dokładniej wyjaśnić odpowiedź Henry'ego, można również użyć określonych kodów błędów, od strony argumentu raise_application_error i odpowiednio je obsługiwać po stronie klienta. Na przykład:

Załóżmy, że procedury PL/SQL, tak aby sprawdzić istnienie rekordu lokalizacji:

PROCEDURE chk_location_exists 
    (
     p_location_id IN location.gie_location_id%TYPE 
    ) 
    AS 
     l_cnt INTEGER := 0; 
    BEGIN 
     SELECT COUNT(*) 
     INTO l_cnt 
     FROM location 
     WHERE gie_location_id = p_location_id; 

     IF l_cnt = 0 
     THEN 
      raise_application_error(
      gc_entity_not_found, 
      'The associated location record could not be found.'); 
     END IF; 
    END; 

raise_application_error pozwala podnieść specyficzny kod błędu. W nagłówku pakietu, można zdefiniować: gc_entity_not_found INTEGER := -20001;

Jeśli potrzebujesz innych kodów błędów dla innych typów błędów, można zdefiniować inne kody błędów używając -20002, -20003 itp

Następnie na kliencie z boku, można zrobić coś takiego (ten przykład dla C#):

/// <summary> 
/// <para>Represents Oracle error number when entity is not found in database.</para> 
/// </summary> 
private const int OraEntityNotFoundInDB = 20001; 

I można wykonać swój kod w try/catch

try 
{ 
    // call the chk_location_exists SP 
} 
catch (Exception e) 
{ 
    if ((e is OracleException) && (((OracleException)e).Number == OraEntityNotFoundInDB)) 
    { 
     // create an EntityNotFoundException with message indicating that entity was not found in 
     // database; use the message of the OracleException, which will indicate the table corresponding 
     // to the entity which wasn't found and also the exact line in the PL/SQL code where the application 
     // error was raised 
     return new EntityNotFoundException(
      "A required entity was not found in the database: " + e.Message); 
    } 
} 
7

Używasz RAISE_APPLICATION_ERROR, aby utworzyć wyjątek/błąd stylu Oracle, który jest specyficzny dla Twojego kodu/potrzeb. Dobre ich wykorzystanie pomaga w tworzeniu kodu, który jest klarowniejszy, łatwiejszy w utrzymaniu i łatwiejszy w debugowaniu.

Na przykład, jeśli mam aplikację wywołanie procedury przechowywanej, które dodaje użytkownikowi, a użytkownik już istnieje, będziesz zwykle wrócić błąd jak:

ORA-00001: unique constraint (USERS.PK_USER_KEY) violated 

Oczywiście tego błędu i związanego wiadomości są nie jest unikalny dla zadania, które próbujesz wykonać. Stworzenie własnych błędów aplikacji Oracle pozwala lepiej określić cel działania i przyczynę problemu.

raise_application_error(-20101, 'User ' || in_user || ' already exists!'); 

Teraz twój kod aplikacji może napisać procedurę obsługi wyjątku, aby przetworzyć ten konkretny warunek błędu. Pomyśl o tym, jako o sposobie, w jaki Oracle będzie komunikować warunki błędu, których Twoja aplikacja oczekuje w "języku" (z braku lepszego terminu), który zdefiniowałeś i jest bardziej znaczący dla domeny problemowej twojej aplikacji.

Należy pamiętać, że błędy zdefiniowane przez użytkownika muszą mieścić się w zakresie od -20000 do -20999.

Następujące link dostarcza wiele dobrych informacji na ten temat i ogólnie wyjątki Oracle.

Powiązane problemy