I have a PL/SQL function similar to this (pseudo code) :
function foobar() return sys_refcursor as
select_cursor sys_refcursor;
begin
open select_cursor for
select
a, b, c, d, e, f, g, h, i, j
from
table_a
left join table_b on ...
left join table_c on ...
left join table_d on...
left join table_e on ...
...
where
...
;
return select_cursor;
end;
As you can see, the type of the cursor is not simply table_a%rowtype
. It's something too complex to just declare (EDIT: that's not entirely true, see the answer by MT0
)
How do I count the number of rows returned by the function?
Constraints:
I have found lots of answer here, but never for counting on an unknown type.
For example:
function count_nodes(
p_cursor in sys_refcursor
)
return number is
v_node_row ???; -- unknown type
v_count number := 0;
begin
loop
fetch p_cursor into v_node_row;
exit when p_cursor%NOTFOUND;
v_count := v_count + 1;
end loop;
close p_cursor;
return v_count;
end;
I've asked the AI, but it hallucinated that I can just FETCH INTO
a dummy variable of type NUMBER
if the first column in the function's SELECT
is a NUMBER
(which it is!). But then when I run the query, I get:
ORA-06504: PL/SQL: Return types of Result Set variables or query do not match
If the goal is just to count rows then Cast a column from the main table as VARCHAR2 to have always the same datatype. If you need the rest of the columns for some other reasons cast them all (commented out in the code), but for the counting you need just one.
Here is the simulation of the data with your foobar function code:
create or replace function foobar return sys_refcursor as
select_cursor sys_refcursor;
begin
open select_cursor for
SELECT a
FROM ( select CAST(a as VARCHAR2(4000)) as a,
b, -- CAST(b as VARCHAR2(4000)) as b,
c -- CAST(c as VARCHAR2(4000)) as c
from ( Select 1 as id, 456 as a From Dual ) table_a
left join ( Select 1 as id, 'some text' as b From Dual ) table_b on(table_b.id = table_a.id)
left join ( Select 1 as id, Trunc(SYSDATE) as c From Dual ) table_c on(table_c.id = table_b.id)
where a > 400
);
return select_cursor;
end;
... now create another function that should do the count ...
CREATE OR REPLACE FUNCTION COUNT_REF_C RETURN NUMBER AS
c sys_refcursor := foobar;
v_a Varchar2(4000);
-- v_b Varchar2(4000);
-- v_c Varchar2(4000);
i NUMBER(6) := 0;
Begin
LOOP
FETCH c INTO v_a; --, v_b, v_c;
EXIT WHEN c%NOTFOUND;
i := i + 1;
END LOOP;
RETURN i;
End;
... Select the function's returned value ...
Select COUNT_REF_C From Dual;
-- R e s u l t :
-- COUNT_REF_C
-- -----------
-- 1