You didn't specify Oracle database version you use.
If it is 11g, then fetch
clause won't work (as it didn't exist yet):
SQL> select * from dept
2 fetch next 1 rows only;
fetch next 1 rows only
*
ERROR at line 2:
ORA-00933: SQL command not properly ended
Another answer suggested not to use a cursor nor a loop at all - that perfectly makes sense, but then you have to write some more code to avoid TOO_MANY_ROWS
(as you can't fit two rows into scalar variables) and, possibly, NO_DATA_FOUND
. With a cursor, you don't have to worry about that as Oracle handles it for you.
Therefore, you could do what you described - run only one loop iteration. But, using a loop at all? Do just open - fetch - close
. It means that your code might look like this (based on Scott's sample schema as I don't have your tables).
Query that "simulates" yours fetches sums of salaries per departments. I'm interested in the highest salary.
SQL> select d.dname, sum(e.sal) sumsal
2 from emp e join dept d on d.deptno = e.deptno
3 group by d.dname
4 order by sumsal desc;
DNAME SUMSAL
-------------- ----------
RESEARCH 10875 --> that's what I want
SALES 9400
ACCOUNTING 8750
The procedure:
SQL> declare
2 cursor find_c is
3 select d.dname, sum(e.sal) sumsal
4 from emp e join dept d on d.deptno = e.deptno
5 group by d.dname
6 order by sumsal desc;
7 cur_r find_c%rowtype;
8 lv_dname dept.dname%type;
9 begin
10 open find_c;
11 fetch find_c into cur_r;
12
13 if cur_r.sumsal > 0 then
14 lv_dname := cur_r.dname;
15 end if;
16
17 dbms_output.put_line('Picked DNAME = ' || lv_dname ||
18 '. Now, do something here, execute some more code');
19
20 -- some code goes here
21 dbms_output.put_line('First iteration is over; that''s the end');
22 close find_c;
23 end;
24 /
Picked DNAME = RESEARCH. Now, do something here, execute some more code --> good, RESEARCH is here
First iteration is over; that's the end
PL/SQL procedure successfully completed.
SQL>
Just to show that without cursor you might get some problems:
TOO_MANY_ROWS:
SQL> declare
2 l_dname dept.dname%type;
3 l_sumsal number;
4 begin
5 select d.dname, sum(e.sal) sumsal
6 into l_dname, l_sumsal
7 from emp e join dept d on d.deptno = e.deptno
8 group by d.dname
9 order by sumsal desc;
10 dbms_output.put_line('Query executed');
11 end;
12 /
declare
*
ERROR at line 1:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at line 5
NO_DATA_FOUND:
SQL> declare
2 l_dname dept.dname%type;
3 l_sumsal number;
4 begin
5 select d.dname, sum(e.sal) sumsal
6 into l_dname, l_sumsal
7 from emp e join dept d on d.deptno = e.deptno
8 where 1 = 2 --> will cause NO_DATA_FOUND
9 group by d.dname
10 order by sumsal desc;
11 dbms_output.put_line('Query executed');
12 end;
13 /
declare
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 5
SQL>
Of course, you can fix that (e.g. using exception handler section), but - why bother?
[EDIT, based on your comment]
If cursor returns more than a single row for each ID and you want to skip the rest, one option to do that is to use ROW_NUMBER
analytic function to "sort" rows and then fetch only the first one for each ID. In my example based on Scott's tables, that would looks like this:
cursor find_c is
select dname, sumsal
from (select d.dname, sum(e.sal) sumsal,
row_number() over (partition by d.dname order by sum(e.sal) desc) rn
from emp e join dept d on d.deptno = e.deptno
group by d.dname
)
where rn = 1;
Adjust it to your data model.