Reputation: 217
I am returning a ref cursor(P_CUR_SUMMARY) and then taking count of the same query to return a string (WARN# / ERROR). I want to eliminate the Count query.
This proc is using an existing framework so I cant return the string with the ref cursor.
I dont want to create a temp table and store data. This will remove the Count query but increase IO.
Any other option to eliminate the Count query? I just want to know if the ref cursor has ANY records. Not interested in actual count.
Procedure:
V_MAIN_TITLE and P_CUR_SUMMARY - OUT parameters
...
OPEN P_CUR_SUMMARY FOR
select * from emp...
...
select count(1) into V_CNT from emp...
...
IF V_CNT > 0 then
SELECT 'WARN#' INTO V_MAIN_TITLE FROM dual;
ELSE
SELECT 'ERROR' INTO V_MAIN_TITLE FROM dual;
END IF;
Upvotes: 0
Views: 56
Reputation: 142753
As you were told, you'll have to fetch from a cursor in order to find out what it contains (use %NOTFOUND
or %FOUND
cursor attributes for such a purpose). If there's something to be returned, re-open the cursor (otherwise you'd lose the first row, the one you used to check what's in there).
Here's an example:
SQL> create or replace procedure p_test
2 (par_deptno in number, par_main_title out varchar2, par_cur_summary out sys_refcursor)
3 is
4 r_emp emp%rowtype;
5 begin
6 open par_cur_summary for
7 select *
8 from emp
9 where deptno = par_deptno;
10
11 -- fetch in order to find out whether there's something returned by the cursor
12 fetch par_cur_summary into r_emp;
13 if par_cur_summary%notfound then
14 par_main_title := 'ERROR';
15 else
16 par_main_title := 'WARN#';
17
18 -- now, re-open the cursor; otherwise, you'd lose the first row, the one
19 -- that has been fetched for "testing" purpose
20 open par_cur_summary for
21 select *
22 from emp
23 where deptno = par_deptno;
24 end if;
25 end;
26 /
Procedure created.
Let's test it:
SQL> var l_cur_sum refcursor
SQL> var l_mai_tit varchar2(30)
SQL> exec p_test(37, :l_mai_tit, :l_cur_sum);
PL/SQL procedure successfully completed.
SQL> print l_mai_tit
L_MAI_TIT
---------------------------------------------------------------------------------------
ERROR
SQL> print l_cur_sum
ERROR:
ORA-01002: fetch out of sequence
no rows selected
SQL> exec p_test(10, :l_mai_tit, :l_cur_sum);
PL/SQL procedure successfully completed.
SQL> print l_mai_tit
L_MAI_TIT
---------------------------------------------------------------------------------------
WARN#
SQL> print l_cur_sum
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ---------- ---------- ---------- ----------
7782 CLARK MANAGER 7839 09.06.1981 2450 10
7839 KING PRESIDENT 17.11.1981 5000 10
7934 MILLER CLERK 7782 23.01.1982 1300 10
SQL>
Look what happens if you don't re-open the cursor (by commenting those lines out):
if par_cur_summary%notfound then
par_main_title := 'ERROR';
else
par_main_title := 'WARN#';
/*
open par_cur_summary for
select *
from emp
where deptno = par_deptno;
*/
end if;
SQL> exec p_test(10, :l_mai_tit, :l_cur_sum);
PL/SQL procedure successfully completed.
SQL> print l_mai_tit
L_MAI_TIT
----------------------------------------------------------------------------------------
WARN#
SQL> print l_cur_sum
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ---------- ---------- ---------- ----------
7839 KING PRESIDENT 17.11.1981 5000 10
7934 MILLER CLERK 7782 23.01.1982 1300 10
SQL>
See? CLARK is lost.
Upvotes: 2
Reputation: 16001
The number of rows that will be returned is not known until the query is executed (i.e. when rows are fetched). When the cursor has merely been opened that is still in the future.
Perhaps it makes more sense for the client to handle the condition where no rows are returned and raise its own errors.
Upvotes: 1