Error creating Procedure - sql

I'm getting some error with a proc I have created. The proc body is :-
CREATE OR REPLACE PROCEDURE suppress_termination_charge(v_curr_date IN DATE)
IS
TYPE suppress_term_cust_type IS RECORD (id NUMBER(11),pev NUMBER(11),piv NUMBER(11));
TYPE cur_suppress_term_cust IS REF CURSOR RETURN suppress_term_cust_type;
v_count NUMBER(4);
v_serv_item suppress_term_cust_type;
v_serv_itm_pev service_item.price_excluding_vat%TYPE;
v_serv_itm_piv service_item.price_including_vat%TYPE;
BEGIN
v_count:=0;
IF NULL=v_curr_date THEN
SELECT sysdate INTO v_curr_date FROM dual;
END IF;
OPEN cur_suppress_term_cust FOR
SELECT id AS id,price_excluding_vat AS pev,price_including_vat AS piv FROM service_items;
LOOP
FETCH cur_suppress_term_cust INTO v_serv_item;
EXIT WHEN cur_suppress_term_cust%NOTFOUND;
v_comment := 'Price changed from ('||v_serv_item.pev||', '||v_serv_item.piv||') to (0,0) (PEV, PIV) on '||v_curr_date||' for managed cease';
UPDATE service_items
SET price_including_vat=0, price_excluding_vat=0 , comments= v_comment
WHERE id = v_serv_item.id;
v_count:=v_count+1;
IF v_count=5000 THEN
COMMIT;
v_count:=0;
END IF;
END LOOP;
CLOSE cur_suppress_term_cust;
END;
/
The errors are as follows:-
SQL> SHOW ERROR;
Errors for PROCEDURE SUPPRESS_TERMINATION_CHARGE:
LINE/COL ERROR
-------- -----------------------------------------------------------------
19/30 PLS-00103: Encountered the symbol "IS" when expecting one of the
following:
. ( % ; for
23/2 PLS-00103: Encountered the symbol "FETCH" when expecting one of
the following:
constant exception <an identifier>
<a double-quoted delimited-identifier> table LONG_ double ref
char time timestamp interval date binary national character
nchar
LINE/COL ERROR
-------- -----------------------------------------------------------------
41/2 PLS-00103: Encountered the symbol "CLOSE" when expecting one of
the following:
end not pragma final instantiable order overriding static
member constructor map

I see errors but not the ones you reported:
SELECT sysdate INTO v_curr_date FROM dual;
v_curr_date is an input parameter and can't be used as a target of SELECT or FETCH.
OPEN cur_suppress_term_cust FOR...
FETCH cur_suppress_term_cust INTO v_serv_item;
EXIT WHEN cur_suppress_term_cust%NOTFOUND.
cur_suppress_term_cust is a TYPE, not a cursor variable.
v_comment := ...
v_comment is not declared.
Try fixing these issues and see if things improve.
Share and enjoy.

Related

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

Error in returning record from function in Oracle PL/SQL

DECLARE
TYPE type_supplier IS
RECORD(supp_phone supplier.supplier_phone%TYPE,
supp_status supplier.supplier_status%TYPE);
FUNCTION fn_supplier(supp_name supplier.supplier_name%TYPE)
RETURN type_supplier
IS supp type_supplier;
BEGIN
select supplier_phone, supplier_status
into supp.supp_phone, supp.supp_status
from supplier
where supplier_name = supp_name;
RETURN supp;
END;
The question is: Create a function that returns Phone Number and status for inputted supplier name. Supplier table has supplier_id, supplier_name, supplier_address, supplier_email, supplier_phone, supplier_status.
I am getting error in above code as:
Error report -
ORA-06550: line 16, column 4:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
begin function pragma procedure
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I don't know hoe to return multiple values from PL/SQL function. I'm using record type for that but getting the error.
I am open for any solution, changes or alternative methods..
Your declaration of the TYPE is not correct.
You can use the OBJECT type and use it as follows:
create TYPE type_supplier IS
OBJECT(supp_phone supplier.supplier_phone%TYPE,
supp_status supplier.supplier_status%TYPE);
/
FUNCTION fn_supplier(supp_name supplier.supplier_name%TYPE)
RETURN type_supplier
IS supp type_supplier;
BEGIN
select supplier_phone, supplier_status
into supp.supp_phone, supp.supp_status
from supplier
where supplier_name = supp_name;
RETURN supp;
END;
/
In PL/SQL what's commonly done is to return an opened cursor which the caller can then walk through. For example:
FUNCTION fn_supplier(supp_name supplier.supplier_name%TYPE)
RETURN SYS_REFCURSOR
IS
csr SYS_REFCURSOR
BEGIN
OPEN csr FOR
SELECT SUPPLIER_PHONE, SUPPLIER_STATUS
FROM SUPPLIER
WHERE SUPPLIER_NAME = pinSupplier_name;
RETURN csr;
END fn_supplier;
Then the caller of the function looks something like:
DECLARE
csrSupplier SYS_REFCURSOR;
vSupplier_phone SUPPLIER.SUPPLIER_PHONE%TYPE;
vSupplier_status SUPPLIER.SUPPLIER_STATUS%TYPE;
BEGIN -- some anonymous
csrSupplier := fn_supplier('Cthulhu, Inc.'); -- why deal with the lesser evil?
LOOP
FETCH csrSupplier INTO vSupplier_phone, vSupplier_status;
EXIT WHEN cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Phone=' || vSupplier_phone ||
' Status=' || vSupplier_status);
END LOOP;
CLOSE csrSupplier;
END;

Using "BEGIN" keyword improperly

I am getting an error in the code below. I have added an arror <------ where the problem is.
The error message says that a THEN is expected, but when I use THEN, then it says that a BEGIN is expected.
Error(27,6): PLS-00103: Encountered the symbol "BEGIN" when expecting one of the following: then and or The symbol "then" was substituted for "BEGIN" to continue.
Error(30,6): PLS-00103: Encountered the symbol "END" when expecting one of the following: , ; return returning
What am I doing wrong?
create or replace PROCEDURE "sp_updateUserPassword"(newUserPwd IN VARCHAR2, curIsoUserUID IN NUMBER)
IS
curUserID NUMBER;
userDateCreated DATE;
oldUserPwd VARCHAR2(255);
BEGIN
SELECT ISOUID INTO curUserID FROM ISOUSERS WHERE ISOUID=curIsoUserUID;
SELECT DATECREATE INTO userDateCreated FROM ISOUSERS WHERE ISOUID=curIsoUserUID;
SELECT PASSWORD INTO oldUserPwd FROM ISOUSERS WHERE ISOUID=curIsoUserUID;
IF(newUserPwd = oldUserPwd)
THEN
raise_application_error(-20000, 'The new password must be different from the previous password');
RETURN;
END IF;
IF NOT EXISTS
(
SELECT ISOUID
FROM OLDUSERPASSWORDS
WHERE ISOUID=curIsoUserUID
)
BEGIN <------------ Error is here
INSERT INTO OLDUSERPASSWORDS(ISOUID, DATECREATE, DATELASTCHANGE, CURRENTPASS, OLDPASS)
VALUES(curUserID, userDateCreated, SYSDATE, newUserPwd, oldUserPwd)
END;
/*raise_application_error(-20000, 'TEST');*/
END "sp_updateUserPassword";
Update
Corrected the code, so it now looks like this:
IF NOT EXISTS
(
SELECT ISOUID
FROM OLDUSERPASSWORDS
WHERE ISOUID=curIsoUserUID
)
THEN
BEGIN
INSERT INTO OLDUSERPASSWORDS(ISOUID, DATECREATE, DATELASTCHANGE, CURRENTPASS, OLDPASS)
VALUES(curUserID, userDateCreated, SYSDATE, newUserPwd, oldUserPwd)
END;
END IF;
I am getting this error:
Error(30,7): PL/SQL: ORA-00933: SQL command not properly ended
Error(31,7): PLS-00103: Encountered the symbol "IF" when expecting one of the following: ; <an identifier> <a double-quoted delimited-identifier>
Perhaps it's just a minor error that I am missing?
PL/SQL Syntax Error for IF THEN ELSE
Correct syntax is:
IF condition THEN
statements
END IF;
Your code is effectively:
IF condition THEN
BEGIN
statements
END;
Corrected
IF NOT EXISTS
(
SELECT ISOUID
FROM OLDUSERPASSWORDS
WHERE ISOUID=curIsoUserUID
)
THEN
BEGIN <------------ Error is NOT here
INSERT INTO OLDUSERPASSWORDS(ISOUID, DATECREATE, DATELASTCHANGE, CURRENTPASS, OLDPASS)
VALUES(curUserID, userDateCreated, SYSDATE, newUserPwd, oldUserPwd);
END;
END IF;
You are getting your first error because you need to add a THEN clause before the BEGIN block to make the syntax of the ID statement complete and correct.
You are getting the second error:
Error(30,7): PL/SQL: ORA-00933: SQL command not properly ended
because you have not completed your INSERT statement. Terminate it with a semicolon and that should fix that error.
IF NOT EXISTS
(
SELECT ISOUID
FROM OLDUSERPASSWORDS
WHERE ISOUID=curIsoUserUID
)
THEN
BEGIN
INSERT INTO OLDUSERPASSWORDS(ISOUID, DATECREATE, DATELASTCHANGE, CURRENTPASS, OLDPASS)
VALUES(curUserID, userDateCreated, SYSDATE, newUserPwd, oldUserPwd);
END;
END IF;
You forgot the THEN before the BEGIN, that goes with the IF NOT EXISTS.

Incomplete/Malformed cursor

I have a PL/SQL script to perform some aggregation tasks. I am having compilation errors, logic is not top priority at this moment as that can be changed once the errors are resolved. The script is as follows :
SET SERVEROUTPUT ON;
ALTER SESSION SET NLS_DATE_FORMAT = 'dd-MON-yy';
CREATE OR REPLACE PROCEDURE updateFeaturePerformanceTable
(noOfDays IN NUMBER, runDate IN DATE, timeSpan IN VARCHAR2)
AS
CURSOR c_feature_performance IS
SELECT distinct mkt_id,dow,device_type,feature_name
FROM gfmdev.feature_performance
WHERE timespan = 'ONE_DAY'
AND feature_performance_day >= TO_DATE('17-AUG-15','dd-MON-yy');
rowsExtracted c_feature_performance%ROWTYPE;
extractDate DATE;
timespan_test varchar2(20);
BEGIN
OPEN c_feature_performance;
extractDate := runDate - noOfDays;
timespan_test := timeSpan;
LOOP
FETCH c_feature_performance INTO rowsExtracted;
EXIT WHEN c_feature_performance%NOTFOUND;
dbms_output.put_line(extractDate || ' ' || timespan_test);
INSERT INTO gfmdev.feature_performance
SELECT
rowsExtracted.mkt_id,
rowsExtracted.dow,
rowsExtracted.device_type,
rowsExtracted.feature_name,
SUM(OPS),
SUM(GV_COUNT),
runDate,
timespan_test
FROM gfmdev.feature_performance
WHERE feature_performance_day BETWEEN extractDate AND runDate
AND timespan = 'ONE_DAY'
AND mkt_id = rowsExtracted.mkt_id
AND dow = rowsExtracted.dow
AND device_type = rowsExtracted.device_type
AND feature_name = rowsExtracted.feature_name
group by mkt_id, dow, device_type, feature_name, timespan;
END LOOP;
CLOSE c_feature_performance;
EXCEPTION
WHEN TOO_MANY_ROWS THEN
dbms_output.put_line('Trying to insert too many rows in SELECT...INTO');
ROLLBACK;
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('No rows returned in SELECT...INTO');
ROLLBACK;
WHEN STORAGE_ERROR THEN
dbms_output.put_line('Too much data to handle! Storage error');
ROLLBACK;
WHEN OTHERS THEN
dbms_output.put_line('Oops! Something went wrong');
ROLLBACK;
RAISE;
END updateFeaturePerformanceTable;
Show compilation errors:
SHOW ERRORS PROCEDURE updateFeaturePerformanceTable;
Run the procedure:
DECLARE
runDate DATE;
BEGIN
FOR j IN 0 .. 5 LOOP
SELECT (TO_DATE('17-AUG-15','dd-MON-yy') + j) INTO runDate FROM dual;
updateFeaturePerformanceTable(6,runDate, 'ONE_WEEK');
END LOOP;
DBMS_OUTPUT.PUT_LINE(' WEEKLY RECORDS UPDATED ');
FOR j IN 0 .. 28 LOOP
SELECT (TO_DATE('17-AUG-15','dd-MON-yy') + j) INTO runDate FROM dual;
updateFeaturePerformanceTable(29,runDate, 'ONE_MONTH');
END LOOP;
DBMS_OUTPUT.PUT_LINE(' MONTHLY RECORDS UPDATED ');
COMMIT;
END;
/
When I execute it I get the following error message :
Errors for PROCEDURE UPDATEFEATUREPERFORMANCETABLE:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/9 PLS-00341: declaration of cursor 'C_FEATURE_PERFORMANCE' is
incomplete or malformed
5/3 PL/SQL: SQL Statement ignored
6/15 PL/SQL: ORA-00942: table or view does not exist
8/16 PL/SQL: Item ignored
16/3 PL/SQL: SQL Statement ignored
16/36 PLS-00320: the declaration of the type of this expression is
incomplete or malformed
21/3 PL/SQL: SQL Statement ignored
LINE/COL ERROR
-------- -----------------------------------------------------------------
36/22 PL/SQL: ORA-00904: "ROWSEXTRACTED"."FEATURE_NAME": invalid
identifier
36/22 PLS-00320: the declaration of the type of this expression is
incomplete or malformed
updateFeaturePerformanceTable(6,runDate, 'ONE_WEEK');
*
Any help on where I am going wrong is highly appreciated?
PL/SQL is a framework for running SQL statements programmatically. So often we find that PL/SQL errors are caused by the SQL errors in our code.
That is the case here. You have several PL/SQL errors indicating that the Cursor declaration is invalid. And why is it invalid? This line holds the answer:
6/15 PL/SQL: ORA-00942: table or view does not exist
So the problem is, the owner of the procedure UPDATEFEATUREPERFORMANCETABLE (ugly name by the way) does not have rights on gfmdev.feature_performance.
To solve, the table owner GFMDEV needs to grant SELECT and INSERT directly to the account which owns this procedure.
SQL> conn gfmdev/password
SQL> grant select, insert on feature_performance to whoever;
Note that granting privileges through a view won't cut it. The Oracle security model only permits us to build objects - PL/SQL programs, views - with privileges granted directly to our user.

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