Simple common error ORA-06550 in PL/SQL cursor - oracle

This is simple PL/SQL block and I have very simple error, ORA-06550 but I can't find it, pls Help me to solve this error..........
Question: Display category wise prize of most costly item
create table menu
(
item_id number primary key,
name_ varchar2(20),
prize number,
category varchar(15)
);
create table order_
(
o_id number primary key,
item_id number references menu(item_id),
table_no number,
qty number
);
SQL> declare
2 cursor data1 is select max(prize) as "prize_", category
3 from menu
4 group by category;
5
6 cursor data2(pr number, cat varchar(15)) is
7 select prize, name_, category
8 from menu
9 where prize = pr and category = cat;
10
11
12 data1_cat varchar(15);
13 data1_pri number;
14
15 data2_cat varchar(15);
16 data2_pri number;
17 data2_name varchar(15);
18 begin
19 open data1;
20 open data2;
21
22 fetch data1 into data1_pri, data1_cat;
23 while data1%found
24 loop
25 fetch data2(data1_pri, data1_cat) into data2_pri, data2_name, data2_cat;
26 while data2%found
27 loop
28 dbms_output.put_line(data2_name || ' ' || data2_pri || ' ' || data2_cat);
29 fetch data2(data1_pri, data1_cat) into data2_pri, data2_name, data2_cat;
30 end loop;
31
32
33 fetch data1 into data1_pri, data1_cat;
34 end loop;
35 close data2;
36 close data1;
37 end;
38 /
Error is blow
ERROR at line 6:
ORA-06550: line 6, column 40:
PLS-00103: Encountered the symbol "(" when expecting one of the following:
:= . ) , # % default character
The symbol ":=" was substituted for "(" to continue.
ORA-06550: line 25, column 20:
PLS-00103: Encountered the symbol "(" when expecting one of the following:
. into bulk
ORA-06550: line 25, column 80:
PLS-00103: Encountered the symbol ";" when expecting one of the following:
. ( , % from
ORA-06550: line 29, column 24:
PLS-00103: Encountered the symbol "(" when expecting one of the following:
. into bulk
ORA-06550: line 29, column 84:
PLS-00103: Encountered the symbol ";" when expecting one of the following:
. ( , % from
ORA-06550: line 35, column 5:
PLS-00103: Encountered the symbol "CLOSE" when expecting one of the following:
end not pragma final instantiable order overriding static
member constructor map

So your anonymous block has way too much mess in it. ORA-06550 is not your problem, the PLS-00103 is and together with ORA-06550 it marks a place where you messed up your code.
First off, your cursor declaration is not according to syntax scheme in documentation. cursor data2(pr number, cat varchar(15)) should be cursor data2(pr number, cat varchar), notice how your first error says ORA-06550: line 6, column 40: PLS-00103: Encountered the symbol "(" when expecting one of the following: := . ) , # % default character, because on line 6 it encountered ( as part of varchar(15) which shouldn't be there.
Your cursor handling is all over the place. Cursor parameters are provided when cursor is being opened not when it is fetched, also you are opening and closing cursor data2 outside of the loop which means that data in the loop are not changed while fetched. Fetch syntax is plain wrong as I mentioned before, no parameters are provided to cursor when data are fetched. This all can be fixed but I would like to propose an cleaner and easier alternative how to call your cursors (unless you have to use open, fetch, close in your assignment):
declare
cursor data1 is select max(prize) as "prize_", category
from menu
group by category;
cursor data2(pr number, cat varchar) is
select prize, name_, category
from menu
where prize = pr and category = cat;
begin
for c in data1 loop
for i in data2(c."prize_", c.category) loop
dbms_output.put_line(i.name_ || ' ' || i.prize || ' ' || i.category);
end loop;
end loop;
end;
/
Here is fixed cursor usage of your original code and I advice you to read more into cursors for example here, I added comments to provide a better look into what is happening in the code:
declare
cursor data1 is select max(prize) as "prize_", category
from menu
group by category;
cursor data2(pr number, cat varchar) is
select prize, name_, category
from menu
where prize = pr and category = cat;
data1_cat varchar(15);
data1_pri number;
data2_cat varchar(15);
data2_pri number;
data2_name varchar(15);
begin
-- Open cursor data1 and start looping over data in cursor
open data1;
loop
-- Fetch cursor data1 values into variables
fetch data1 into data1_pri, data1_cat;
-- Check if cursor provided data, if not exit loop
exit when data1%notfound;
-- Open cursor data2 with parameters from variables filled with data from cursor data1 and start looping over data in cursor
open data2(data1_pri, data1_cat);
loop
-- Fetch cursor data2 values into variables
fetch data2 into data2_pri, data2_name, data2_cat;
-- Check if cursor provided data, if not exit loop
exit when data2%notfound;
-- Handle variables as needed
dbms_output.put_line(data2_name || ' ' || data2_pri || ' ' || data2_cat);
end loop;
-- Close cursor data2 as new cursor will be opened in next loop and without closing it would lead to ORA-06511: PL/SQL: cursor already open
close data2;
end loop;
-- Close cursor data1 as good practice and possibly to avoid ORA-01000: maximum open cursors exceeded
close data1;
end;
/

Related

Apex button and procedure

Im trying to create button in Apex which execute given procedure. As input values I gave two date fields called Poczatek and Koniec. The button should execute this procedure on submit. It perfectly works in Oracle, but throw a lot of errors in Apex.
set serveroutput on
create or replace procedure KORELACJA(:Poczatek, :Koniec)
IS
miasto VARCHAR(25);
korelacja NUMBER;
cursor c1 is
SELECT TEMP.nazwa, corr(TEMP.temperatura, WILGOTNOSC.wilg)
FROM TEMP INNER JOIN WILGOTNOSC
on TEMP.nazwa = WILGOTNOSC.nazwa
and TEMP.data = WILGOTNOSC.data
WHERE TEMP.data between to_date(:Poczatek, 'YYYY-MM-DD') and to_date(:Koniec, 'YYYY-MM-DD')
GROUP BY TEMP.nazwa;
BEGIN
DBMS_OUTPUT.put_line(RPAD('Miasto',10)||RPAD('Korelacja',10));
open c1;
FOR i IN 1..6
LOOP
commit;
fetch c1 into miasto, korelacja;
DBMS_OUTPUT.put_line(RPAD(miasto,10)||RPAD(korelacja,10));
END LOOP;
close c1;
END KORELACJA;
/
Errors look like this:
1 error has occurred
ORA-06550: line 2, column 5: PL/SQL: ORA-00922: missing or invalid option
ORA-06550: line 2, column 1: PL/SQL: SQL Statement ignored ORA-06550: line 6,
column 11: PLS-00103: Encountered the symbol "NUMBER" when expecting one of the
following: := . ( # % ; ORA-06550: line 9, column 18: PLS-00103: Encountered the symbol "JOIN" when
expecting one of the following: , ; for group having intersect minus order start
union where connect
Anyone knows the solution?
I'd suggest you to leave the procedure in the database; call it from Apex.
As you said that it works OK, I'm not going to examine the code. Just modify the first line:
create or replace procedure KORELACJA(par_Poczatek in date,
par_Koniec in date)
is ...
Then, in Apex process, call the procedure as
korelacja(:p1_poczatek, :p2_koniec);
Note that you might need to apply TO_DATE function to those items, using appropriate format mask, such as
korelacja(to_date(:p1_poczatek, 'dd.mm.yyyy',
to_date(:p1_koniec , 'dd.mm.yyyy');
If you insist on keeping the procedure in Apex' process (I wouldn't recommend it), the you don't need CREATE PROCEDURE but an anonymous PL/SQL block. It won't accept any parameters - use Apex items directly.
declare
miasto VARCHAR(25);
korelacja NUMBER;
cursor ...
WHERE TEMP.data between to_date(:p1_Poczatek, 'YYYY-MM-DD') ...
begin
...
end;

Oracle pl/sql - Use associative array with user created record

I'm trying to use an associative array with the element type of a user defined record. This array is to print the first name, last name, and grade of a student.
SET SERVEROUTPUT ON
DECLARE
TYPE studentRec IS RECORD (
STUDENT_ID studentdb.student.student_id%TYPE,
FIRST_NAME STUDENTDB.STUDENT.FIRST_NAME%TYPE,
LAST_NAME STUDENTDB.STUDENT.LAST_NAME%TYPE,
GRADE STUDENTDB.GRADE.NUMERIC_GRADE%TYPE
);
CURSOR studentCursor IS
SELECT STUDENT.STUDENT_ID, STUDENT.FIRST_NAME, STUDENT.LAST_NAME, AVG(GRADE.NUMERIC_GRADE) AS GRADE
FROM STUDENTDB.STUDENT
INNER JOIN STUDENTDB.GRADE
ON STUDENTDB.STUDENT.STUDENT_ID = STUDENTDB.GRADE.STUDENT_ID
GROUP BY STUDENT.STUDENT_ID, STUDENT.FIRST_NAME, STUDENT.LAST_NAME ;
sr studentRec;
TYPE studentArray IS TABLE OF studentRec INDEX BY PLS_INTEGER;
vars studentArray;
BEGIN
FOR rec IN studentCursor LOOP
vars(rec.STUDENT_ID) := rec.FIRST_NAME || ' ' || rec.LAST_NAME || ' has grade ' || rec.GRADE;
END LOOP;
FOR ind IN vars.FIRST .. vars.LAST LOOP
DBMS_OUTPUT.PUT_LINE(vars(ind));
END LOOP;
END;
This throws:
Error report - ORA-06550: line 27, column 27: PLS-00382: expression is
of wrong type ORA-06550: line 27, column 3: PL/SQL: Statement ignored
ORA-06550: line 33, column 1: PLS-00306: wrong number or types of
arguments in call to 'PUT_LINE' ORA-06550: line 33, column 1: PL/SQL:
Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
You don't need a RECORD declaration here, although you could use it if you know it. It is better to use CURSOR%ROWTYPE. syntax as shown. There is also no need of associative array, as your indexes are going to be numbers anyway.
Also, instead of looping through the CURSOR, you could use BULK COLLECT INTO.
You cannot directly pass vars(ind) to .PUT_LINE() . It should refer to specific column names.
SET serveroutput ON
DECLARE
CURSOR studentcursor IS
SELECT student.student_id,
student.first_name,
student.last_name,
AVG(grade.numeric_grade) AS GRADE
FROM studentdb.student
inner join studentdb.grade
ON studentdb.student.student_id =
studentdb.grade.student_id
GROUP BY student.student_id,
student.first_name,
student.last_name;
TYPE studentarray
IS TABLE OF studentcursor%ROWTYPE;
vars STUDENTARRAY;
BEGIN
OPEN studentcursor;
FETCH studentcursor BULK COLLECT INTO vars;
FOR ind IN vars.first .. vars.last LOOP
dbms_output.put_line(vars(ind).student_id
||','
|| vars(ind).first_name
||','
||vars(ind).last_name
||','
|| vars(ind).grade);
END LOOP;
END;

Using 2 explicit cursors.

*/I am trying to use 2 explicit cursors, it shows these errors
{:ERROR at line 42:
ORA-06550: line 42, column 1:
PLS-00306: wrong number or types of arguments in call to 'PUT_LINE'
ORA-06550: line 42, column 1:
PL/SQL: Statement ignored } */
declare
v_CITY AIRPORT.CITY%TYPE;
v_ARRIVAL_TIME SCHEDULE.ARRIVAL_TIME%TYPE;
v_fnumber FLIGHT.FNUMBER%TYPE;
v_CITY1 AIRPORT.CITY%TYPE;
v_ARRIVAL_TIME1 SCHEDULE.ARRIVAL_TIME%TYPE;
v_fnumber1 FLIGHT.FNUMBER%TYPE;
/* First cursor */
CURSOR get_tables IS
select airp2.CITY , S. ARRIVAL_TIME,S.fnumber
from schedule S, FLIGHT F, airport airp1, airport airp2
where airp1.apcode = DEPARTURE_APCODE and airp2.apcode = ARRIVAL_APCODE AND ARRIVAL_APCODE ='BWI'and S.FNUMBER= F.FNUMBER AND
TO_CHAR(TRUNC(S.DEPARTURE_TIME)) = date'2017-11-12'
ORDER BY airp1.CITY, ARRIVAL_TIME ;
/* Second cursor */
CURSOR get_columns IS
select DISTINCT airp2.CITY , S. DEPARTURE_TIME,S.fnumber
from schedule S, FLIGHT F, airport airp1,FLIGHT_RESERVATION FL, airport airp2
where airp1.apcode = ORIGIN_APCODE and airp2.apcode = DESTINATION_APCODE AND ORIGIN_APCODE ='BWI'and S.FNUMBER= F.FNUMBER AND
TO_CHAR(TRUNC(S.DEPARTURE_TIME)) = date'2017-11-12'
ORDER BY airp2.CITY, DEPARTURE_TIME ;
BEGIN
-- Open first cursor
OPEN get_tables;
LOOP
FETCH get_tables INTO v_CITY, v_ARRIVAL_TIME, v_fnumber;
-- Open second cursor
OPEN get_columns;
LOOP
FETCH get_columns INTO v_CITY1, v_ARRIVAL_TIME1, v_fnumber1;
DBMS_output.put_line(v_CITY1, v_ARRIVAL_TIME1, v_fnumber1);
CLOSE get_tables;
END LOOP;
CLOSE get_columns;
END LOOP;
END;
DBMS_OUTPUT.PUT_LINE takes only one argument, so to output multiple values you have to convert them to character strings and concatenate them together. Change your PUT_LINE call to
DBMS_output.put_line('CITY1=' || TO_CHAR(v_CITY1) ||
' ARRIVAL_TIME=' || TO_CHAR(v_ARRIVAL_TIME1) ||
' FNUMBER=' || TO_CHAR(v_fnumber1));
Best of luck.

Error trying to print Collection variable by index

Can anyone identify what is wrong with the following code. specifically the first dbms_output line. The second one prints fine. But first one gives this error:
Error at line 2
ORA-06550: line 15, column 53:
PLS-00201: identifier 'MYCOLL' must be declared
ORA-06550: line 15, column 1:
PL/SQL: Statement ignored
DECLARE
CURSOR c1
IS
SELECT sub_provider_address_id sub_id, phone, extension
FROM sub_provider_address;
TYPE coll_type IS TABLE OF c1%ROWTYPE;
my_coll coll_type;
BEGIN
OPEN c1;
FETCH c1
BULK COLLECT INTO my_coll;
dbms_output.put_line(' my_coll first row id has '|| mycoll(1).phone );
dbms_output.put_line(' my_coll now has '|| my_coll.last );
END;
You're declaring the variable as my_coll:
my_coll coll_type;
And on the line that's erroring you're referring to it as mycoll:
dbms_output.put_line(' my_coll first row id has '|| mycoll(1).phone );
So you're just missing an underscore, and it should be:
dbms_output.put_line(' my_coll first row id has '|| my_coll(1).phone );
Your coll_type is not an associated array type.
you have to use something like this:
TYPE coll_type IS TABLE OF c1%ROWTYPE index by pls_integer;
Use this as an example:
declare
cursor c1 is
select 1 id from dual
;
type coll_type is table of c1%ROWTYPE index by pls_integer;
l_coll_type coll_type;
begin
open c1;
fetch c1 bulk collect into l_coll_type;
close c1;
dbms_output.put_line('Output:' || l_coll_type(1).id);
end;
Output:1

ORA-06550, PLS-00103, ORA-06512 on function

I have no idea what to do. I wrote a function, compiled it with no errors but then when I run the code I got:
ORA-0650: line 3, column 14:
PLS-00103: Encountered the symbol "/" when expecting one of the following:
:= . ( # % ; not null range default character
ORA-06512: at line 58
Vendor code 6550
This is the function:
create or replace
FUNCTION "GET_MUSICIAN_FUN"
(
i_mus_id IN musicians.id%type
)
RETURN musicians%ROWTYPE
AS
o_mus_rec musicians%ROWTYPE;
BEGIN
SELECT m.id, m.first_name, m.last_name, m.born, m.died , m.picture_path, m.bio
INTO o_mus_rec
FROM musicians m
WHERE id = i_mus_id;
RETURN o_mus_rec;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20005, 'Found nothing.');
WHEN TOO_MANY_ROWS THEN
RAISE_APPLICATION_ERROR(-20006, 'Found too many.');
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20007, 'Cannot get musician.');
END GET_MUSICIAN_FUN;
EDIT:
When I call it with:
declare
result musicians%rowtype;
begin
result := get_musician_fun(53);
end;
/
I get : "anonymous block completed"
But when calling it from PHP:
$con = oci_connect("yoni", "yoni", "//localhost/xe");
$s = oci_parse($con, "begin :rc := GET_MUSICIAN_FUN(53); end;");
$rc = oci_new_cursor($con);
oci_bind_by_name($s, ":rc", $rc, -1, OCI_B_CURSOR);
oci_execute($s); // line 41
oci_execute($rc, OCI_DEFAULT);
oci_fetch_all($rc, $res, null, -1, OCI_FETCHSTATEMENT_BY_ROW); // line 43
return $res;
I get:
Warning
: oci_execute(): ORA-06550: line 1, column 14:
PLS-00382: expression is of wrong type
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored in... on line 41
Warning
: oci_fetch_all(): ORA-24338: statement handle not executed in... on line 43
I'm no php expert but your trying to fetch an oracle row object into php.
rowtype are used only inside oracle pl/sql code.
try this approach
create or replace function get_musician_fun( i_mus_id in musicians.id%type)
return varchar2
as
musician_row varchar2(32000);
begin
select m.id||','|| m.first_name||','|| m.last_name||','|| m.born||','|| m.died ||','|| m.picture_path||','|| m.bio
into o_mus_rec
from musicians m
where id = i_mus_id;
return musician_row;
exception
when no_data_found then
raise_application_error(-20005,'found nothing.');
when too_many_rows then
raise_application_error(-20006,'found too many.');
when others then
raise_application_error(-20007,'cannot get musician.');
end get_musician_fun;
and split the result on your php like a csv.
look at the revised raise_application_error bit the code above.
you might be better of querying the database and fetching the row
without a stored procedure.

Resources