Reputation: 390
I need to return a cursor within a function:
CREATE OR REPLACE FUNCTION test_cursor (
bigstring IN VARCHAR2
)
RETURN cursor
IS
row_test table_colors := table_colors(bigstring);
c1 CURSOR;
BEGIN
OPEN c1 FOR
select * from cars where color IN (select column_value
from table(row_test));
RETURN c1;
END test_cursor;
table_colors
is:
create or replace type table_colors as table of varchar2(20);
But when I test it passing like blue, red, pink, white
or 'blue', 'red', 'pink', 'white'
always throws the same error
ORA-06502: PL/SQL; numeric or value error: character string buffer too small
on this line row table_colors := table_colors(bigstring);
What I am doing wrong here?
Upvotes: 0
Views: 1236
Reputation: 2101
Please show the definition of table_colors
. It appears that table_colors(bigstring)
is returning a value incompatible with assignment to table_colors
.
As a matter of good practice, initialization of non trivial values should be done inside of the begin ... end
rather than in the definition section. That allows you to trap the error within the function or procedure rather than the error cascading outwards. For example, rather than:
IS
row_test table_colors := table_colors(bigstring);
c1 CURSOR;
BEGIN ...
You should use
IS
row_test table_colors;
c1 CURSOR;
BEGIN
row_test := row_test;
...
Upvotes: 0
Reputation: 231661
The problem is that bigstring
is a single scalar value that may happen to contain commas and single quotes not a list of values. You would need to parse the string to extract the data elements. If each of the individual elements within bigstring
happens to be a valid Oracle identifier, you could use the built-in dbms_utility.comma_to_table
function. Were it my system, though, I'd feel more comfortable with my own parsing function. Assuming that bigstring
is just a comma-separated list, I'd use a version of Tom Kyte's str2tbl function
create or replace function str2tbl( p_str in varchar2 )
return table_colors
as
l_str long default p_str || ',';
l_n number;
l_data table_colors := table_colors();
begin
loop
l_n := instr( l_str, ',' );
exit when (nvl(l_n,0) = 0);
l_data.extend;
l_data( l_data.count ) := ltrim(rtrim(substr(l_str,1,l_n-1)));
l_str := substr( l_str, l_n+1 );
end loop;
return l_data;
end;
Now, you can realistically implement str2tbl
using regular expressions in a single SQL statement as well. That might be a touch more efficient. I'd expect, however, that string parsing is well down on your list of performance issues so I would tend to stick with the simplest thing that could possibly work.
Your procedure would then become
CREATE OR REPLACE FUNCTION test_cursor (
bigstring IN VARCHAR2
)
RETURN sys_refcursor
IS
row_test table_colors := str2tbl(bigstring);
c1 sys_refcursor;
BEGIN
OPEN c1 FOR
select * from cars where color IN (select column_value
from table(row_test));
RETURN c1;
END test_cursor;
Upvotes: 1