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

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;
/

Related

ELSE Statement Not Printing

I have a stored procedure that searches if a customer ID exists in a database. The procedure has two parameters, the customer ID and a number to indicated 1 if it was found and 2 if it is not. I am using and ELSE statement to print to screen is the ID is found or not. The valid ID I enter prints a valid message, but the invalid (non-existing ID) I enter does not. My ELSE put_line in my else block is not being executed(printed). Here is the procedure and the two function calls I make to it using a valid ID and an invalid ID. Why won't the put_line in the ELSE block print?
CREATE OR REPLACE PROCEDURE find_customer(cus_customer_id IN NUMBER, found OUT NUMBER) IS
cus_id NUMBER;
BEGIN
SELECT customer_id INTO cus_id FROM customers WHERE customer_id = cus_customer_id;
IF (cus_id != cus_customer_id)
THEN
found:=0;
dbms_output.Put_line('This Customer ID does not exist!');
ELSE
found:=1;
dbms_output.Put_line('This Customer ID (' || cus_id ||'} was found!');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
found:=0;
WHEN OTHERS THEN
dbms_output.Put_line('error');
END;
-- FUNCTION CALL -- Find Customer Existing 319--
DECLARE
fnd NUMBER;
id NUMBER:= 319;
BEGIN
find_customer(id, fnd);
dbms_output.Put_line(fnd);
END;
-- FUNCTION CALL -- Find Customer Non-Existing 320--
DECLARE
fnd NUMBER;
id NUMBER:= 320;
BEGIN
find_customer(id, fnd);
dbms_output.Put_line(fnd);
END;
This is the output I am currently getting:
Procedure FIND_CUSTOMER compiled
This Customer ID (319) was found!
1
PL/SQL procedure successfully completed.
0
PL/SQL procedure successfully completed.
You are trying to find a row that does not exist and a NO_DATA_FOUND exception is thrown and then execution of the main block terminates and switches to executing the EXCEPTION block so the IF statement is never reached.
What you appear to want is:
CREATE PROCEDURE find_customer(
cus_customer_id IN CUSTOMERS.CUSTOMER_ID%TYPE,
found OUT NUMBER
) IS
cus_id NUMBER;
BEGIN
SELECT customer_id
INTO cus_id
FROM customers
WHERE customer_id = cus_customer_id;
found:=1;
dbms_output.Put_line('This Customer ID (' || cus_id ||'} was found!');
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.Put_line('This Customer ID does not exist!');
found:=0;
END;
/
Note: catching OTHERS in the exception handler is considered bad practice as it will hide all errors and you will not know when or why they happen. What you want to do is catch the expected exceptions and then, unless you have a very good reason not to, let the other exceptions cause a failure that you can then debug and fix.
db<>fiddle here

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

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

PLS-00103: Encountered the symbol "&" when expecting one of the following

PLS-00103: Encountered the symbol "&" when expecting one of the following...
code:
Declare
num number;
Begin
num := &num;
if num > 0 then
dbms_output.put_line(‘Hello’);
end if;
end;
/
I'm not sure why I'm getting this message when I'm not seeing anything wrong.
Oracle Live SQL is a tool for trying out SQL and PL/SQL but it doesn't support substitution variable syntax (&var.).
Instead, you can create tables, populate them with data, then run SQL or PL/SQL using them, e.g.:
create table inputs (num number);
insert into inputs values (10);
Declare
num number;
Begin
select num into num from inputs;
if num > 0 then
dbms_output.put_line('Hello');
end if;
end;
/
(p.s. I had to fix the quotes around 'Hello' for this to work)
Oracle live does not support & for get value.
Instead you can initialize the Variable
Declare
num number := 10;
Begin
if num > 0 then
dbms_output.put_line(‘Hello’);
end if;
end;
/

PLSQL -- calling function to calculate with char(1) and number variables

I'm just now teaching myself SQL and PLSQL and have haven't had too much trouble debugging the regular SQL, but I'm trying to call a PLSQL function that is throwing errors that I can't figure out from the Oracle docs and other online resources. I'm using Oracle SQL-Developer.
I've tried these but they are not helpful in this case:
How to return a record from an existing table from an Oracle PL/SQL function?
Writing a function in plsql
Oracle PLSQL function call into a second function
Can't seem to subract two numbers in a PLSQL function
I've tried writing the same function 2 different ways for practice:
Create Function Calc_Tax
(Quantity IN Number,Unit_Price IN Number,Taxable IN VarChar2)
Return Number IS amt Number;
Declare
price := Quantity * Unit_Price;
Begin
IF Taxable = 'Y' THEN
amt := price + 0.06 * price;
ELSE
amt := price;
END IF;
Return amt;
End;
-- or --
Create Or Replace Function Calc_Tax
(Quantity IN Number,Unit_Price IN Number,tax IN Sale_Item.Taxable%TYPE)
Return Number IS amt Number;
Declare
price := Quantity * Unit_Price;
Begin
IF tax = 'Y' THEN
amt := price + 0.06 * price;
ELSE
amt := price;
END IF;
Return amt;
End;
I had some trouble declaring the 'tax' parameter as a varchar2(1) so I left it just varchar2 which the docs seem to say is default for 1 space (if I read that right). Of course, I'd rather do it properly and declare the size of the varchar explicitly.
This is how I'm calling it:
DECLARE
g_last Guest.First_Name%type := 'Richard';
g_last Guest.Last_Name%type := 'Wharton';
g_id Guest.Guest_ID%type;
s_g_id Stay.Guest_ID%type;
sho_id Stay.Hotel_ID%type;
h_id Hotel.Hotel_ID%type;
h_name Hotel.Hotel_Name%type;
i_id Sale_Item.Item_ID%type;
i_name Sale_Item.Item_Name%type;
i_tax Sale_Item.Taxable%type;
cs_id Charge.Stay_ID%type;
c_date Charge.Trans_Date%type;
c_quant Charge.Quantity%type;
c_uprice Charge.Unit_Price%type;
BEGIN
SELECT H.Hotel_ID, H.Hotel_Name,C.Item_ID, Item_Name, C.Trans_Date, C.Quantity,
C.Unit_Price,Taxable INTO h_id,h_name,i_id,i_name,c_date,c_quant,c_uprice
FROM Hotel H,Charge C Where cs_id = (Select Stay_ID From Stay Where Guest_ID =
(Select Guest_ID From Guest Where First_Name='Richard' And Last_Name='Wharton'));
--WHERE id = c_id;
dbms_output.put_line
('Guest ' ||g_first || g_last || ' bought ' || i_name || ' with tax ' || Calc_Tax
(c_quant,c_uprice,i_tax));
END;
And it's throwing errors:
Error(18,1): PLS-00103: Encountered the symbol "DECLARE"
Error(43,4): PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: ( begin case declare end exception exit for goto if loop mod null pragma raise return select update while with <an identifier> <a double-quoted delimited-identifier> <a bind variable> << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge
Here's the schema:
I'm just learning now, so I'm sure that any junior SQL programmers can quickly show me where I'm going wrong.
You don't use DECLARE inside a procedure or function -- use the AS keyword instead to indicate the variable declaration "block."
You also cannot put a constraint on parameters (e.g. you can have VARCHAR2 but not VARCHAR2(10) -- See Oracle docs
You also shouldn't have a semi-colon following your return statement.
Create Function Calc_Tax (Quantity IN Number, Unit_Price IN Number, Taxable IN VarChar2)
Return Number
AS
My_Variable VARCHAR2(2000);
BEGIN
-- code
END Calc_Tax;

Oracle select query error inside procedure [duplicate]

This question already has answers here:
Oracle Procedure error (PLS-00428)
(5 answers)
Closed 8 years ago.
I'm getting error while I'm running select query inside procedure. Error print as follow:
[Error] PLS-00428 (24: 9): PLS-00428: an INTO clause is expected in this SELECT statement
CREATE OR REPLACE PACKAGE BODY PACK_EMP
IS
PROCEDURE find_employee(
P_ID NUMBER,
P_ERR OUT VARCHAR2
)
IS
BEGIN
IF P_ID IS NULL THEN
SELECT * FROM EMPLOYEE WHERE ID = P_ID
ELSE
P_ERR := 'An error occured on database!!';
END IF;
EXCEPTION
WHEN OTHERS THEN
P_ERR := SQLERRM;
END;
END;
CREATE OR REPLACE PACKAGE BODY PACK_EMP
IS
PROCEDURE find_employee(
P_ID NUMBER,
P_ERR OUT VARCHAR2,
V_VAL OUT VARCHAR
)
IS
BEGIN
IF P_ID IS NULL THEN
SELECT FIRTSNAME ||' '||LASTNAME INTO V_VAL FROM EMPLOYEE WHERE ID = P_ID
ELSE
P_ERR := 'An error occured on database!!';
END IF;
EXCEPTION
WHEN OTHERS THEN
P_ERR := SQLERRM;
END;
END;
Use a rowtype. Also I think you meant to say "IF P_ID IS NOT NULL THEN..." because if it is null then your select will never work.
CREATE OR REPLACE PACKAGE BODY PACK_EMP
IS
PROCEDURE find_employee(
P_ID NUMBER,
P_ERR OUT VARCHAR2
)
IS
empRec employee%rowtype; /* ADD THIS LINE */
BEGIN
IF P_ID IS NOT NULL THEN
SELECT * into empRec FROM EMPLOYEE WHERE ID = P_ID;
--now you can reference the columns like this: empRec.id
ELSE
P_ERR := 'An error occured on database!!';
END IF;
EXCEPTION
WHEN OTHERS THEN
P_ERR := SQLERRM;
END;
END;