ORA-06550: line 6, column 31: PLS-00103:Encountered the symbol ")" - sql

ORA-06550: line 6, column 31: PLS-00103: Encountered the symbol ")"
when expecting one of the following: (
I don't know how to manage error
create or replace PROCEDURE Get_StarInfo(Stars in out starsin.starname%type, cnt out integer, avg out float)
is
begin
select starname, count(title), avg(length) into Stars, cnt, avg
from starsin, movie
where movietitle=title
and movieyear=year
and starname=Stars
group by starname;
exception
when others then
cnt := -1;
avg := -1;
end;
declare
Stars starsin.starname%type := 'harrison ford';
cnt integer:=3;
avg float:=3.1;
begin
get_starinfo(Stars,cnt,avg);
end;

As Alex commented, it was a bad idea calling variable or parameter the same as built-in functions. Though, you can make it work but - you'd rather not do it that way.
I don't have your tables so I'm using Scott's sample schema, calculating some values from its emp table based on department number (that's your "stars").
SQL> create or replace PROCEDURE Get_StarInfo(Stars in out number, cnt out integer, avg out float)
2 is
3 begin
4 select deptno, count(*), avg(sal)/20 into Stars, cnt, avg
5 from emp
6 where deptno = stars
7 group by deptno;
8 exception
9 when others then
10 cnt := -1;
11 avg := -1;
12 end;
13 /
Procedure created.
This is how you called it and got the error:
SQL> set serveroutput on;
SQL> declare
2 Stars number := 10;
3 cnt integer; -- :=3;
4 avg float; -- :=3.1;
5 begin
6 get_starinfo(Stars,cnt,avg);
7 dbms_output.put_line('count = ' || cnt ||', average = ' || "AVG");
8 end;
9 /
get_starinfo(Stars,cnt,avg);
* --> see where the asterisk points to? That's where the error is!
ERROR at line 6:
ORA-06550: line 6, column 31:
PLS-00103: Encountered the symbol ")" when expecting one of the following:
(
ORA-06550: line 8, column 4:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the
following:
end not pragma final instantiable persistable order
overriding static member constructor map
SQL>
Now, how to use that "avg" of yours:
a side note: cnt and avg local variables (lines #3 and #4) are supposed to accept values returned by the procedure, so there's no point in setting their initial values
Oracle, by default, uses uppercase for object names, column names etc., so - if you enclose avg into double quotes and switch to uppercase (line #6), there's no error any more
So:
SQL> set serveroutput on;
SQL> declare
2 Stars number := 10;
3 cnt integer; -- :=3;
4 avg float; -- :=3.1;
5 begin
6 get_starinfo(Stars,cnt,"AVG");
7 dbms_output.put_line('count = ' || cnt ||', average = ' || "AVG");
8 end;
9 /
count = 3, average = 145.835
PL/SQL procedure successfully completed.
SQL>
Once again: as suggested, just don't do that. What we usually do, is to use prefix (such as v_ for "variable" or l_ for "local variable" or p_ for "parameter", etc.)

Related

When I am using listagg in procedure I am getting plsql numeric or value error

Ora-06502: pl/SQL: numeric or value error.
select listagg(listagg(l_comb,';') within group (order by rownum) as l_comb into out_output_string
From (select product_id|| ':' || rule_group as l_comb from dt1 ).
My expected output for example - 1234:12;456:23
If your out_output_string parameter is type VARCHAR2 and it is used in a SQL statement, the parameter will return a string up to the length of
4000 characters (11g and earlier) or MAX_STRING_SIZE (12c and above).
Your error is occurring because a local variable in a separate PL/SQL procedure is too small. See How to fix Character string buffer too small error in OUT variable in Stored Procedure
I would recommend adding an EXCEPTION block in the ADD_LIST procedure. Use UTL_CALL_STACK to trace the program flow. Follow the stack trace to find the variable that is sized too small.
Sample package
CREATE OR REPLACE PACKAGE test_pkg
AS
pkg_ten_chars VARCHAR2(10); -- pkg_variable that is too small
PROCEDURE add_list(out_output_string OUT VARCHAR2);
PROCEDURE add_list_passthrough(out_output_string2 OUT VARCHAR2);
END test_pkg;
CREATE OR REPLACE PACKAGE BODY test_pkg
AS
PROCEDURE add_list(out_output_string OUT VARCHAR2)
IS
BEGIN
WITH dt1
AS
(select 1234 product_id, 12 rule_group from dual
UNION
select 456 product_id, 23 rule_group from dual
)
SELECT LISTAGG(product_id|| ':' || rule_group, ';') WITHIN GROUP (ORDER BY ROWNUM)
INTO out_output_string -- return variable can be up to MAX_STRING_SIZE of SQL statement
FROM dt1;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('[how code got here - ' || SQLERRM || ']');
-- start at depth = 2 because depth = 1 will be the line below
FOR d in 2 .. utl_call_stack.dynamic_depth() LOOP
dbms_output.put_line('Depth: ' || d
|| ', Procedure: ' || utl_call_stack.concatenate_subprogram(utl_call_stack.subprogram(d))
|| ', Line: '|| to_char(utl_call_stack.unit_line(d))
);
END LOOP;
END add_list;
PROCEDURE add_list_passthrough(out_output_string2 OUT VARCHAR2)
IS
BEGIN
add_list(test_pkg.pkg_ten_chars); -- (line=33) errors b/c package variable is too small
out_output_string2 := test_pkg.pkg_ten_chars;
END add_list_passthrough;
END test_pkg;
Using an anonymous PL/SQL block to call the different procedures.
DECLARE
l_local_max_chars VARCHAR2(4000); -- local variable of max characters
l_local_ten_chars VARCHAR2(10); -- local variable of ten characters
BEGIN
test_pkg.add_list_passthrough(l_local_max_chars); -- (line=5) errors in add_list_passthrough
test_pkg.add_list(l_local_max_chars); -- OK
test_pkg.add_list(l_local_ten_chars); -- (line=7) errors b/c local variable too small
END;
Results
[how code got here - ORA-06502: PL/SQL: numeric or value error]
Depth: 2, Procedure: TEST_PKG.ADD_LIST_PASSTHROUGH, Line: 33
Depth: 3, Procedure: __anonymous_block, Line: 5
[how code got here - ORA-06502: PL/SQL: numeric or value error]
Depth: 2, Procedure: __anonymous_block, Line: 7

Error "PLS-00302: component 'MIN' must be declared" trying to find min/max value

Im getting the error "PLS-00302: component 'MIN' must be declared" when trying to find min/max value for a distance trip. Any thoughts?
create or replace procedure longandshortdist (p_distance in number)
is
cursor longshortcursor is
select source_town, destination_town, distance
from distances
where distance = p_distance;
distance_row longshortcursor%rowtype;
begin
for distance_row in longshortcursor
loop
dbms_output.put_line('source town is: ' || distance_row.source_town || 'destination
town is: ' || distance_row.destination_town || 'shortest trip is: ' ||
distance_row.min(distance) || 'longest trip is: ' || distance_row.max(distance));
end loop;
end;
The error code I'm getting:
12/1 PL/SQL: Statement ignored
12/169 PLS-00302: component 'MIN' must be declared
Errors: check compiler log
Read comments; seem to be very useful. Meanwhile, I tried to figure out what you wanted and this might be "it".
For sample data as
SQL> SELECT *
2 FROM distances
3 ORDER BY distance;
SOURCE_TOW DESTINAT DISTANCE
---------- -------- ----------
Zagreb Karlovac 40
Zadar Split 120
Koprivnica Osijek 200
procedure doesn't accept any parameters (because, you'd fetch only rows whose distance is equal to p_distance (once again, see Connor's comment)) and loops through all rows in a table.
Loop itself displays all towns, but MIN and MAX distance are displayed only once - out of the loop, once you actually calculate their values.
SQL> CREATE OR REPLACE PROCEDURE longandshortdist
2 IS
3 mindist NUMBER := 1E6;
4 maxdist NUMBER := 0;
5 BEGIN
6 FOR cur_r
7 IN (SELECT source_town, destination_town, distance FROM distances)
8 LOOP
9 mindist := LEAST (mindist, cur_r.distance);
10 maxdist := GREATEST (maxdist, cur_r.distance);
11
12 DBMS_OUTPUT.put_line (
13 'source town is: '
14 || cur_r.source_town
15 || ', destination town is: '
16 || cur_r.destination_town
17 || ', distance is: '
18 || cur_r.distance);
19 END LOOP;
20
21 DBMS_OUTPUT.put_line (
22 'shortest trip is: ' || mindist || ', longest trip is: ' || maxdist);
23 END;
24 /
Procedure created.
Testing:
SQL> SET SERVEROUTPUT ON
SQL> EXEC longandshortdist;
source town is: Zagreb, destination town is: Karlovac, distance is: 40
source town is: Zadar, destination town is: Split, distance is: 120
source town is: Koprivnica, destination town is: Osijek, distance is: 200
shortest trip is: 40, longest trip is: 200
PL/SQL procedure successfully completed.
SQL>
That is because the min and max are aggregate functions used within a query and not inside a block.
Example:
SELECT max(a.f) max, min(a.f) min
FROM (
select 1 f from dual
union all
select 2 f from dual
union all
select 3 f from dual) a
Result:
MAX
MIN
3
1
OR
I think you are trying to get the min / max of two values , if so check the links below :
max function greatest
min function least

oracle trim function with numeric pram

Declare a Type as a table of number(38,0).
In a procedure of function.
code example:
ids_list := Type(....); // load data to variable
ids_list.trim(count);
I don't quite understand what will do to trim a list with a numeric list with numeric parameter. What will ids_list.trim(count) happens?
If I understood you correctly, you're talking about a collection and its trim method. If that's so, then documentation says:
Decreasing the Size of a Collection (TRIM Method)
This procedure has two forms:
TRIM removes one element from the end of a collection.
TRIM(n) removes n elements from the end of a collection.
If you want to remove all elements, use DELETE without parameters.
Code you posted doesn't do anything because of
SQL> declare
2 type numlist is table of number;
3 n numlist := numlist(1,2,3, 10);
4 begin
5 n.trim(count);
6 end;
7 /
n.trim(count);
*
ERROR at line 5:
ORA-06550: line 5, column 10:
PLS-00204: function or pseudo-column 'COUNT' may be used inside a SQL statement only
ORA-06550: line 5, column 3:
PL/SQL: Statement ignored
SQL>
Perhaps you meant to use the count method instead (n.count)?
SQL> declare
2 type numlist is table of number;
3 n numlist := numlist(1,2,3, 10);
4 begin
5 dbms_output.put_line('Number of elements in that collection = ' || n.count);
6
7 n.trim(n.count);
8
9 dbms_output.put_line('Number of elements in that collection AFTER trim = ' || n.count);
10 end;
11 /
Number of elements in that collection = 4
Number of elements in that collection AFTER trim = 0
PL/SQL procedure successfully completed.
SQL>
If so, then - as you can see - it removes all elements from the collection.

plsql stops running after the first loop (Error: "Subscript outside of limit")

DECLARE
TYPE Lname IS VARRAY(15)
OF employees.last_name%TYPE;
v1 Lname:= Lname();
CURSOR c1 IS
SELECT employee_id
FROM employees
WHERE department_id = 50;
LEN NUMBER(2);
I NUMBER(2);
BEGIN
-- Print out the contents of this Varray while populating
DBMS_OUTPUT.PUT_LINE('This printout is in order of populating:');
DBMS_OUTPUT.PUT_LINE(CHR(9) || 'Name');
DBMS_OUTPUT.PUT_LINE(CHR(9) || '----');
I := 1;
FOR E IN c1 LOOP
v1.EXTEND();
v1(I) := e.employee_id;
DBMS_OUTPUT.PUT_LINE(CHR(9) || v1(I));
I := I + 1;
END LOOP;
-- Display the maximum size of thisi Varray
LEN := v1.LIMIT;
DBMS_OUTPUT.PUT_LINE('Max size of Varray: ' || LEN);
--Display the total number of the elements with populated values (value is not null)
DBMS_OUTPUT.PUT_LINE('Total elements: ' || v1.COUNT);
--Display the value of the last index
DBMS_OUTPUT.PUT_LINE('Last index value: ' || v1(v1.LAST));
--Print out all of the contents of this Varray (including null elements)
DBMS_OUTPUT.PUT_LINE('This printout is all of the contents of this Varray:');
DBMS_OUTPUT.PUT_LINE(CHR(9) || 'Name');
DBMS_OUTPUT.PUT_LINE(CHR(9) || '----');
FOR I IN 1 .. LEN LOOP
IF v1.EXISTS(I) THEN
DBMS_OUTPUT.PUT_LINE(CHR(9) || v1(I));
ELSE
v1.EXTEND;
DBMS_OUTPUT.PUT_LINE(CHR(9) || v1(I));
END IF;
END LOOP;
END;
/
When I run the above, it runs up to the first loop and displays the name and underneath it the numbers, and then it stops.
It throws the following error:
Error report -
ORA-06532: Subscript outside of limit
ORA-06512: at line 19
ORA-06512: at line 19
06532. 00000 - "Subscript outside of limit"
*Cause: A subscript was greater than the limit of a varray
or non-positive for a varray or nested table.
*Action: Check the program logic and increase the varray limit
if necessary.
I cannot understand why this error is thrown. I want to have an array of size 15 and to display the first 12 employee names from the table to populate v1 and then display it.
Any help is appreciated!
Error is in these lines (DECLARE section):
TYPE Lname IS VARRAY(15) --> 15
LEN NUMBER(2); --> 2
I NUMBER(2); --> 2
It works OK if number of array elements is lower than 15 (which you set in the first line above). However, if number of elements is higher than that number, you're trying to use an element whose number goes beyond that limit.
What to do? Enlarge everything, e.g.
set varray to at least count(*) from employees where department = 50 (I suggest a lot more)
remove precision for those variables
For example:
TYPE Lname IS VARRAY(1000) --> 1000
OF employees.last_name%TYPE;
v1 Lname:= Lname();
CURSOR c1 IS
SELECT employee_id
FROM employees
WHERE department_id = 50;
LEN NUMBER; --> no precision
I NUMBER; --> no precision
Since you are apparently not writing the array to a table just make it and associative array. That doesn't impose a limit on the number of entries.
type lname is table of employees.lname%type
index by pls_integer;
i pls_integer;

oracle pl/sql ora-01722 error

I have a simple oracle statement in my procedure:
update org.security_training_question a
set a.actv_indr = 'N' where a.qstn_id in (v_qstns_to_delete);
v_qstns_to_delete is a parameter being passed. It is a varchar2 field and a.qstn_id is a numeric field.
When calling the Stored Procedure, for v_qstns_to_delete I am passing the following String: "24, 43, 23, 44, 21".
When I run the statement output the stored procedure thenn it runs fine but when I run it as a stored procedure I get an error on the above line saying Invalid Number.
Any clue?
You can't use a "in" clause with a variable like that. One way around it is
declare stmt varchar2(4000);
begin
stmt := 'update org.security_training_question a set a.actv_indr = ''N'' where a.qstn_id in ('||v_qstns_to_delete||')';
execute immediate stmt;
end;
if v_qstns_to_delete is a varchar, you would need to convert it somewhat to let Oracle understand that there may be several items in it. One method would be to convert the string to a table of items.
Supposing qstn_id is a NUMBER column, you would:
SQL> CREATE TYPE tab_number AS TABLE OF NUMBER;
2 /
Type created
SQL> CREATE OR REPLACE FUNCTION to_tab_number(p_in VARCHAR2,
2 p_separator VARCHAR2 DEFAULT ',')
3 RETURN tab_number AS
4 l_result tab_number := tab_number();
5 l_tail LONG := p_in;
6 BEGIN
7 WHILE l_tail IS NOT NULL LOOP
8 l_result.EXTEND;
9 IF instr(l_tail, p_separator) != 0 THEN
10 l_result(l_result.COUNT) := to_number(substr(l_tail,
11 1,
12 instr(l_tail, p_separator) - 1));
13 l_tail := substr(l_tail, instr(l_tail, p_separator) + 1);
14 ELSE
15 l_result(l_result.COUNT) := to_number(l_tail);
16 l_tail := NULL;
17 END IF;
18 END LOOP;
19 RETURN l_result;
20 END;
21 /
Function created
You could then convert a string to a table of number from SQL:
SQL> SELECT * FROM TABLE(to_tab_number('24, 43, 23, 44, 21'));
COLUMN_VALUE
------------
24
43
23
44
21
To do a variable in-list:
SQL> SELECT object_id, owner
2 FROM all_objects
3 WHERE object_id IN (SELECT column_value FROM TABLE(to_tab_number('18,19,20')));
OBJECT_ID OWNER
---------- ------------------------------
18 SYS
19 SYS
20 SYS
More on the same subject on askTom.