Adding an exception (calling function) into procedure - SQL Oracle - sql

Having some problems with adding function calling exception in the procedure. I hope it's just some syntax misstake.
The exception unauthorised is checking if the correct owner of the account deposits money in to the account. To handle that I call function get_authorisation. The code works itself without the exception. Could someone check it? Thank you!
create or replace procedure do_utt(
p_radnr in utt.radnr%type,
p_pnr in utt.pnr%type,
p_knr in utt.knr%type,
p_belopp in utt.belopp%type,
p_datum in utt.datum%type)
declare unauthorised exception;
as
begin
insert into utt(radnr, pnr, knr, belopp, datum)
values (radnr_seq.nextval, p_pnr, p_knr,
p_belopp, sysdate);
if get_authorisation(p_knr) = 0 then
raise unauthorised ;
end if;
commit;
dbms_output.put_line('Balance '|| p_knr || ' is:
'||get_saldo(p_knr));
exception
when unauthorised then
dbms_output.put_line('You are not the owner of the account!');
end;
/
Errors: PROCEDURE DO_UTT
Line/Col: 8/2 PLS-00103: Encountered the symbol "DECLARE" when expecting one of the following:
; is with default authid as cluster order using external
deterministic parallel_enable pipelined result_cache
accessible rewrite
The code for function:
create or replace function get_authorisation (
p_pnr in owner.pnr%type,
p_knr in owner.knr%type)
return number
as
v_authorised number;
v_no_authorised exception;
begin
select count(*)
into v_authorised
from owner
where pnr = p_pnr
and knr = p_knr;
return v_authorised;
exception
when v_no_authorised then
return 0;
end;

You should declare your own excepcion with the PRAGMA EXCEPTION_INIT clause and then throw the exception with RAISE_APPLICATION_ERROR as it's shown in this answer:
https://stackoverflow.com/a/6020523/518
Note: you should use an error code less than -20000 (in the answer -20001 is used)

--I changed the code with PRAGMA EXCEPTION_INIT --
create or replace procedure do_utt(
p_radnr in utt.radnr%type,
p_pnr in utt.pnr%type,
p_knr in utt.knr%type,
p_belopp in utt.belopp%type,
p_datum in utt.datum%type)
as
declare
unauthorised exception;
PRAGMA EXCEPTION_INIT( unauthorised, -20001 );
begin
insert into utt(radnr, pnr, knr, belopp, datum)
values (radnr_seq.nextval, p_pnr, p_knr, p_belopp, sysdate);
commit;
dbms_output.put_line('Balance '|| p_knr || ' is: '||get_saldo(p_knr));
raise_application_error (20001, 'You are not the account owner!');
exception
when get_authorisation = 0 then
dbms_output.put_line( sqlerrm );
end;
Errors: PROCEDURE DO_UTTAG
Line/Col: 8/2 PLS-00103: Encountered the symbol "DECLARE" when expecting one of the following:
begin function pragma procedure subtype type
current cursor delete
exists prior external language
The symbol "begin" was substituted for "DECLARE" to continue.
Line/Col: 19/26 PLS-00103: Encountered the symbol "=" when expecting one of the following:
. then or

Related

Procedure to check if authorized

So I have this function:
create or replace function get_authorization(
p_pnr in bankcustomer.pnr%type,
p_knr in account.cnr%type)
return number
as
v_authorization bankcustomer.pnr%type;
begin
select count(*)
into v_authorization
from bankcustomer,account
where pnr = p_pnr
and cnr = p_cnr;
return v_authorization;
exception
when no_data_found then
return -1;
end;
This returns 1 or 0 if allowed. I need to do a procedure which adds a row in a table called withdraw and that procedure needs to call get_authorization to check if the customer is allowed. This is what i have so far:
create or replace procedure do_withdraw(
p_pnr in withdraw.pnr%type,
p_belopp in withdraw.belopp%type)
as
declare
authorization exception;
begin
insert into uttag(pnr,amount)
values((select pnr from account),p_amount); /*pnr is foreign key in withdraw*/
if user not in (select get_amount(p_pnr) from dual) then
raise authorization;
end if;
exception
when authorization then
raise_application_error(-20007,'Unauthorized!');
commit;
end;
I get alot of error messages and specifically on declare. I really cant wrap my head around this :(
You have few problems with your code -
create or replace procedure do_withdraw(
p_pnr in withdraw.pnr%type,
p_belopp in withdraw.belopp%type)
as
-- declare -- Declare keyword is not used in procedure
authorization exception;
begin
insert into uttag(pnr,amount)
values((select pnr from account), -- This might return multiple rows, So you have to add a where clause in this query.
p_amount); /*pnr is foreign key in withdraw*/
if user <> get_authorization(p_pnr) then -- You are checking current user with amount which should be corrected.
raise authorization;
end if;
commit; -- Commit should be last sattement of procedure
exception
when authorization then
raise_application_error(-20007,'Unauthorized!');
Rollback; -- In exception you should use Rollabck instead of Commit;
end;
So ive tried what you said and think i know what you mean:
create or replace procedure do_withdraw(
p_pnr in withdraw.pnr%type,
p_amount in withdraw.amount%type)
as
-- declare -- Declare keyword is not used in procedure
authorization exception;
begin
insert into withdraw(pnr,amount)
values((select pnr from account where pnr = p_pnr), -- This might return multiple rows, So you have to add a where clause in this query.
p_amount); /*pnr is foreign key in withdraw*/
if user not in (select get_authorization(p_pnr)) then -- You are checking current user with amount which should be corrected.
raise authorization;
end if;
commit; -- Commit should be last sattement of procedure
exception
when authorization then
raise_application_error(-20007,'Unauthorized!');
Rollback; -- In exception you should use Rollabck instead of Commit;
end;
Now i get error: Line/Col: 11/51 PLS-00103: Encountered the symbol ")" when expecting one of the following:. ( , * % & - + /

PLSQL error PLS-00103: Encountered the symbol "CREATE" when expecting one of the following

Hy, I'm trying to solve some task and I wrote this code:
DECLARE
previse EXCEPTION;
nema EXCEPTION;
CREATE OR REPLACE PROCEDURE POVECANJE_CIJENE(NOVA_SIFRA PO_PLOCICE.SIFRA_DOB%TYPE) IS
BEGIN
IF NOVA_SIFRA NOT IN (SELECT SIFRA_DOB FROM PO_DOBAVLJAC) THEN
RAISE nema;
ELSIF (CIJENA+30)>600 THEN
RAISE previse;
ELSE
UPDATE PO_PLOCICE SET CIJENA=CIJENA+30 WHERE SIFRA_DOB=NOVA_SIFRA;
EXCEPTION
WHEN nema THEN
DBMS_OUTPUT.PUT_LINE('Nema te sifre');
WHEN previse THEN
DBMS_OUTPUT.PUT_LINE('Cijena je prešla 600 kn');
END POVECANJE_CIJENE;
BEGIN
EXECUTE POVECANJE_CIJENE(2245);
END;
But it keep saying this error:
ORA-06550: line 4, column 1:
PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:
begin function pragma procedure subtype type
current cursor delete
exists prior
Does anybody know what is the problem?
You can't have a CREATE OR REPLACE PROCEDURE statement inside an anonymous PL/SQL block. If you want to create the procedure as a stored procedure you can create the procedure first:
CREATE OR REPLACE PROCEDURE POVECANJE_CIJENE(NOVA_SIFRA PO_PLOCICE.SIFRA_DOB%TYPE) IS
previse EXCEPTION;
nema EXCEPTION;
BEGIN
IF NOVA_SIFRA NOT IN (SELECT SIFRA_DOB FROM PO_DOBAVLJAC) THEN
RAISE nema;
ELSIF (CIJENA+30)>600 THEN
RAISE previse;
ELSE
UPDATE PO_PLOCICE SET CIJENA=CIJENA+30 WHERE SIFRA_DOB=NOVA_SIFRA;
EXCEPTION
WHEN nema THEN
DBMS_OUTPUT.PUT_LINE('Nema te sifre');
WHEN previse THEN
DBMS_OUTPUT.PUT_LINE('Cijena je prešla 600 kn');
END POVECANJE_CIJENE;
and then call it from an anonymous block
BEGIN
POVECANJE_CIJENE(2245);
END;
Or else you can make the procedure local to the PL/SQL block:
DECLARE
previse EXCEPTION;
nema EXCEPTION;
PROCEDURE POVECANJE_CIJENE(NOVA_SIFRA PO_PLOCICE.SIFRA_DOB%TYPE) IS
BEGIN
IF NOVA_SIFRA NOT IN (SELECT SIFRA_DOB FROM PO_DOBAVLJAC) THEN
RAISE nema;
ELSIF (CIJENA+30)>600 THEN
RAISE previse;
ELSE
UPDATE PO_PLOCICE SET CIJENA=CIJENA+30 WHERE SIFRA_DOB=NOVA_SIFRA;
EXCEPTION
WHEN nema THEN
DBMS_OUTPUT.PUT_LINE('Nema te sifre');
WHEN previse THEN
DBMS_OUTPUT.PUT_LINE('Cijena je prešla 600 kn');
END POVECANJE_CIJENE;
BEGIN
POVECANJE_CIJENE(2245);
END;
Note also that in a PL/SQL block (DECLARE...BEGIN...END) you don't use the EXECUTE statement, which is an SQL*Plus command.
Best of luck.
You can do this (probaj ovako pa ako ti ne radi javi da rješavamo dalje :) )
CREATE OR REPLACE PROCEDURE POVECANJE_CIJENE(NOVA_SIFRA PO_PLOCICE.SIFRA_DOB%TYPE) IS
previse EXCEPTION;
nema EXCEPTION;
l_broj_cijena number;
l_cijena number;
BEGIN
select count(1)
into l_broj_cijena
from PO_DOBAVLJAC
where SIFRA_DOB = NOVA_SIFRA;
select max(cijena)
into l_cijena
from PO_PLOCICE
where SIFRA_DOB=NOVA_SIFRA;
IF l_broj_cijena = 0
THEN
RAISE nema;
ELSIF (l_cijena+30)>600 THEN
RAISE previse;
ELSE
UPDATE PO_PLOCICE SET CIJENA=CIJENA+30
WHERE SIFRA_DOB=NOVA_SIFRA;
END IF;
EXCEPTION
WHEN nema THEN DBMS_OUTPUT.PUT_LINE('Nema te sifre');
WHEN previse THEN DBMS_OUTPUT.PUT_LINE('Cijena je prešla 600 kn');
END POVECANJE_CIJENE;

Oracle not able to insert exception into table

I have below procedure where i am trying to track the exceptions into I_Log table.To test whether its working or not I have made a ORA-00933: SQL command not properly ended error in my query where I am trying to insert into I_OPTION table. When i run this procedure the dbms output line is printing the error below but its not getting inserted into I_Log table:
OTHERS exception in EXT_I_OPTION - ID:1000196-933----ORA-00933: SQL command not properly ended
Below is my procedure:
CREATE OR REPLACE PROCEDURE
"EXT_I_OPTION"(in_id IN NUMBER DEFAULT 0)
AS
err_code VARCHAR(100);
err_msg VARCHAR(100);
in_event_id NUMBER;
in_db_link VARCHAR2(50);
in_env_id NUMBER;
l_sql VARCHAR2(5000);
l_sql1 VARCHAR2(5000);
BEGIN
FOR I_row IN I_cur
LOOP
l_sql2 := INSERT INTO I_OPTION(ID)
select DISTINCT(SO.ID)
)
from Icard I;
END LOOP;
EXCEPTION WHEN OTHERS THEN
err_code := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 200);
INSERT INTO I_log (I_ID)
VALUES (i_id);
RAISE;
COMMIT;
END ext_I_option;
It seems that you have a RAISE before COMMIT; this way, the error will be raised before doing COMMIT, so you don't find data in your log table.
According to suggestions, you should define a procedure to handle your log table:
CREATE OR REPLACE procedure i_LOG (...) AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
Insert into I_LOG(...);
COMMIT;
END;
/
This procedure runs in a separate transaction, so it only does commit of log data, with no conflict with data you modify in your main procedure.
Then you should modify your error handling in this way, avoiding COMMIT statement, that can be really dangerous, saving partial, unconsistent data:
DBMS_OUTPUT.PUT_LINE('OTHERS exception in EXT_I_OPTION - ID:'||to_char(ID) || err_code || '----' || err_msg );
ins_I_LOG(...);
RAISE;

PL/SQL Error PLS-00103 - Encountered symbol xxxx when expecting yyyy

I know these errors are most often caused by typos; that's what I've been finding at least. If my problem is a typo, I cannot see it after ~30 minutes of looking, it's driving me crazy.
My question is: am I doing something fundamentally wrong, or can you see a typo?
PL/SQL:
CREATE OR REPLACE PROCEDURE Replenish_Stock(p_id VARCHAR2, n INT)
AS
no_such_id EXCEPTION;
CURSOR pc IS
SELECT Product_ID FROM Products;
BEGIN
IF p_id IN pc THEN
UPDATE Products
SET Stock_Level = Stock_Level + n
WHERE product_id = p_id;
ELSE
RAISE no_such_id;
END IF;
EXCEPTION
WHEN INVALID_NUMBER THEN
DBMS_OUTPUT.PUT_LINE('Bad integer input, ignoring procedure call.');
WHEN no_such_id THEN
DBMS_OUTPUT.PUT_LINE('Bad Product id, ignoring procedure call.');
END;
/
Error code:
Error(7,14): PLS-00103: Encountered the symbol "PC" when expecting one of the following: (
Thanks for any help.
Your usage of IN and CURSOR is not right. the below should work for you. You can just use SQL%ROWCOUNT to see if the update query impact any rows in the table.
CREATE OR REPLACE PROCEDURE Replenish_Stock(p_id VARCHAR2, n INT)
AS
no_such_id EXCEPTION;
Rows_Updated NUMBER;
BEGIN
UPDATE Products
SET Stock_Level = Stock_Level + n
WHERE product_id = p_id;
IF( SQL%ROWCOUNT = 0) THEN
RAISE no_such_id;
END IF;
EXCEPTION
WHEN INVALID_NUMBER THEN
DBMS_OUTPUT.PUT_LINE('Bad integer input, ignoring procedure call.');
WHEN no_such_id THEN
DBMS_OUTPUT.PUT_LINE('Bad Product id, ignoring procedure call.');
END;
/

Trigger calling procedure error

I am having some troubles with this trigger. I created a procedure to check and see if salary is within a certain boundary. If it fails to fall within a certain range, raise the exception. The problem is even though the procedure compiles with no errors, the trigger can not find the procedure.
set serveroutput on;
create or replace procedure check_salary (
tmp_id in varchar2,
tmp_sal in number
)
IS
v_sal number(6,0) := tmp_sal;
v_min number(6,0);
v_max number(6,0);
ex_fail exception;
cursor cur_select is
select min_salary, job_id, max_salary
from jobs where job_id = tmp_id;
BEGIN
for rec_something in cur_select loop
v_min := rec_something.min_salary;
v_max := rec_something.max_salary;
if v_sal >= v_min and v_sal <= v_max then
raise ex_fail;
end if;
end loop;
exception
when ex_fail then
dbms_output.put_line('Invalid salary ' || v_sal || ' must be between ' || v_min || ' and ' || v_max ||'.');
END;
/
show errors;
create or replace trigger check_salary_trg
after insert or update on employees
for each row
declare
begin
IF UPDATING or INSERTING THEN
execute check_salary(:NEW.job_id, :NEW.salary);
end if;
end;
/
show errors;
The Error Message:
PROCEDURE check_salary compiled
No Errors.
TRIGGER check_salary_trg compiled
Warning: execution completed with warning
5/13 PLS-00103: Encountered the symbol "CHECK_SALARY" when expecting one of the following:
:= . ( # % ; immediate
The symbol ":=" was substituted for "CHECK_SALARY" to continue.
Change it to:
create or replace trigger check_salary_trg
after insert or update on employees
for each row
begin
IF UPDATING or INSERTING THEN
check_salary(:NEW.job_id, :NEW.salary);
end if;
end;
/
When you are executing a procedure within a PL/SQL block, you do not use the
EXECUTE syntax
More information about execute you can check the below link
http://docstore.mik.ua/orelly/oracle/prog2/ch23_01.htm
The stack overflow exception is due to the use of dbms_output.put_line inside check_salary procedure.
SQL*Plus command set serveroutput on reserves little size as default, you must specify the buffer size or remove the dbms_output.put_line from check_salary procedure.
In order to increase default buffer size use this:
set serveroutput on size 1000000