procedura z obsługą wyjatków PL/SQL

0

Witam

Mam problem z napisaniem procedury a dokładniej z wyjątkami do niej. Może ktoś pomoże ? :)
Procedura ma policzyć współczynnik będący ilorazem sumy zarobków do liczby nagród w dziale, którego identyfikator dany jest parametrem, obsłużyć wyjątki użytkownika gdy nie ma takiego działu, w dziale nie pracuje żaden pracownik, nie ma żadnych wypłat w dziale oraz wyjątek systemowy dzielenia przez zero. Nie wiem w jaki sposób wpleść wyjątki w kod aby poprawnie skompilować procedure.

CREATE OR REPLACE PROCEDURE proc 
(identyfikator number, wsp OUT NUMBER)
IS
BEGIN
SELECT SUM(brutto)/COUNT(idnagrody) INTO wsp FROM nagrody
JOIN zarobki USING(idosoby) JOIN osoby USING(idosoby) JOIN dzialy USING(iddzialu)
where iddzialu=identyfikator;
IF (identyfikator) not in (1,2,3,4,5) then
DBMS_OUTPUT.PUT_LINE ('nie ma takiego dzialu');
END IF;
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE('DZIELENIE PRZEZ ZERO');
END proc;

SET SERVEROUTPUT ON;
DECLARE wsp number;
begin
proc(5,wsp);
DBMS_OUTPUT.PUT_LINE(wsp);
end

Dziękuję za wszelką pomoc.

0

To zależy jak chcesz te wyjątki obsługiwać.
Czy chcesz sygnalizować błędy poza procedurę do kodu wywołującego przez swoje wyjątki, który sobie caller wyłapie i obsłuży ?
Czy też chcesz wyłapywać wyjątki i zwracać błędy np. przez dodatkowy parametr w procedurze, i caller będzie sobie badał
ten parametr (0 - OK, <> 0 - kod błędu) ?

Jeśli to pierwsze, to można np. tak:

create or replace
PROCEDURE proc 
(identyfikator NUMBER, wsp OUT NUMBER)
IS
BEGIN
   IF identyfikator = 0 THEN
      raise_application_error(-20100, 'Nie ma takiego działu' );
   ELSIF identyfikator = 1 THEN
      raise_application_error(-20101, 'W dziale nie pracuje żaden użytkownik' );
   ELSIF identyfikator = 2 THEN
      raise_application_error(-20102, 'Nie ma żadnych wypłat w dziale' );
   ELSIF identyfikator = 3 THEN
      RAISE zero_divide;
   ELSE
      wsp := 20000;
   END IF;
END;
/ 
SQL> variable x number
SQL> exec proc( 0, :x );
BEGIN proc( 0, :x ); END;

*
ERROR at line 1:
ORA-20100: Nie ma takiego dzialu
ORA-06512: at "TEST.PROC", line 6
ORA-06512: at line 1


SQL> exec proc( 1, :x );
BEGIN proc( 1, :x ); END;

*
ERROR at line 1:
ORA-20101: W dziale nie pracuje zaden uzytkownik
ORA-06512: at "TEST.PROC", line 8
ORA-06512: at line 1


SQL> exec proc( 2, :x );
BEGIN proc( 2, :x ); END;

*
ERROR at line 1:
ORA-20102: Nie ma zadnych wyplat w dziale
ORA-06512: at "TEST.PROC", line 10
ORA-06512: at line 1

SQL> exec proc( 3, :x )
BEGIN proc( 3, :x ); END;

*
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at "TEST.PROC", line 12
ORA-06512: at line 1


SQL> exec proc( 5, :x );

PL/SQL procedure successfully completed.

SQL> print :x

	 X
----------
     20000
 

A jeśli tę drugą metodą, to np. tak:

create or replace package dzial
is
  err_dzielenie_przez_zero   CONSTANT number := 1; 
  err_nie_ma_takiego_dzialu  CONSTANT number := 2; 
  err_w_dziale_nie_ma_pracownika  CONSTANT number := 3;   
  err_nie_ma_wyplat_w_dziale  CONSTANT number := 4;     
  PROCEDURE proc(identyfikator NUMBER, wsp OUT NUMBER, err OUT NUMBER);
end;
/

create or replace package body dzial
is
PROCEDURE proc(identyfikator NUMBER, wsp OUT NUMBER, err OUT NUMBER)
IS
  nie_ma_takiego_dzialu EXCEPTION ;
  w_dziale_nie_ma_pracownika EXCEPTION ;
  nie_ma_wyplat_w_dziale EXCEPTION;
BEGIN
   IF identyfikator = 0 THEN
      raise nie_ma_takiego_dzialu;
   ELSIF identyfikator = 1 THEN
      raise w_dziale_nie_ma_pracownika;
   ELSIF identyfikator = 2 THEN
      raise nie_ma_wyplat_w_dziale;
   ELSIF identyfikator = 3 THEN
      RAISE zero_divide;
   ELSE
      wsp := 20000;
   END IF;
   err := 0;
EXCEPTION
   WHEN zero_divide           THEN err := err_dzielenie_przez_zero;
   WHEN nie_ma_takiego_dzialu THEN err := err_w_dziale_nie_ma_pracownika;
   WHEN w_dziale_nie_ma_pracownika THEN err := err_w_dziale_nie_ma_pracownika;
   WHEN nie_ma_wyplat_w_dziale THEN err := err_nie_ma_wyplat_w_dziale;
END; -- procedure proc
end; -- package dzial
/
 
SQL> variable err number
SQL> exec dzial.proc( 2, :x, :err );

PL/SQL procedure successfully completed.

SQL> print :err

       ERR
----------
	 4

SQL> exec dzial.proc( 10, :x, :err );

PL/SQL procedure successfully completed.

SQL> print :err

       ERR
----------
	 0

SQL> print :x

	 X
----------
     20000
 
0

Witam
Mam podobny problem, próbuję rozwiązać następujące ćwiczenie (znalezione gdzieś w necie)
Stwórz procedurę wyświetlającą na konsoli wynik dzielenia 2 wartości podanych jako jej parametry. Obsłuż błędy które mogą się pojawić w trakcie działania programu. Do obsługi błędów stwórz oddzielną procedurę z parametrem.
O ile pierwsza część to nie problem

CREATE OR REPLACE PROCEDURE dzielenie(x NUMBER,y NUMBER) IS
wynik NUMBER;
BEGIN
  wynik:=x/y;
  dbms_output.put_line('Wynik dzielenia liczb to '||wynik);
END;

to z drugą nie do końca rozumiem autora i nie wiem jak się zabrać za obsługę błędów. Proszę o pomoc.
Dodam, że jestem początkującym i nie dotarłem jeszcze do pakietów.

0

Byłem u wróżki - powiedziała mi że autor miał na myśli coś takiego:
[code]
SQL> call dzielenie( 20, 0 );
call dzielenie( 20, 0 )
*
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at "TEST.DZIELENIE", line 4
[/code]

Poszukaj w dokumentacji, są tam przykłady jak to obsłużyć
http://docs.oracle.com/cd/B10501_01/appdev.920/a96624/07_errs.htm

0

ok, dzięki za informację, a więc napisałem procedurę 'wyjatki' która obsługuje jakieś 2 wyjątki(1 predefiniowany i jeden mój):

create or replace procedure dzielenie(x number,y number) is
wynik number;
begin
  wynik:=x/y;
  if wynik>5 then wyjatki(1);
  end if;
exception
  when zero_divide then wyjatki(2);
end;

create or replace
procedure wyjatki(ident number) is
  d_licz exception;
  przez_0 exception;
begin
  if ident=1 then
    raise d_licz;
  elsif ident=2 then
    raise przez_0;
  end if;
exception
  when d_licz then dbms_output.put_line('Wynik dzielenia większy od 5');
  when przez_0 then dbms_output.put_line('Nie dziel przez 0');
end;

Czy dobrze to zrozumiałem ? :)

0
bladyk napisał(a)

Czy dobrze to zrozumiałem ? :)

Bardzo dobrze :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1