ROWNUM works only for one row. How to fetch rows after that? - oracle

I want to extract BLOB data and write a file (suggest it should be excel or txt or any other) out of it. A single cell has upto 60k characters. I wanted to write a script that reads whole table with BLOB data and write into a file. In below code ROWNUM works only for one row. what's the alternative? Or is there another script that can help me to achieve my ultimate objective to read BLOB and write file?
SET SERVEROUTPUT ON;
DECLARE
TotalRows NUMBER;
TotalChar NUMBER;
CharCounter NUMBER;
BEGIN
SELECT count(*) INTO TotalRows FROM <TableName>;
--dbms_output.Put_line(RC);
--END;
FOR RC IN 1..TotalRows
LOOP
-----------------Code for Rows starts--------------------------------------------------------------------------------
dbms_output.Put_line('Row '||RC||' Started.');
SELECT Length(<ColumnWithBLOBDataType>) INTO TotalChar FROM <TableName> where **Rownum = RC**;
dbms_output.Put_line('Crossed Char counting query. TotalChar='||TotalChar);
CharCounter:=TotalChar/2000+1;
dbms_output.Put_line('Loop will run these many times= '||CharCounter|| ' and Total Chars=' ||TotalChar);
For CC IN 1..CharCounter
LOOP
dbms_output.Put_line('Trip: '||CC);
END LOOP;
-----------------Code for Rows Ends----------------------------------------------------------------------------------------
TotalChar :=0;
dbms_output.Put_line('Row '|| RC||' Done. TotalChar='|| TotalChar);
END LOOP;
dbms_output.Put_line('Exited loop 1.');
END;

You normally don't use ROWNUM to select rows from a table. It's not safe and not necessary. Normally, you can do it with a single FOR SELECT loop:
DECLARE
CharCounter NUMBER;
part VARCHAR2(30000);
offset NUMBER;
BEGIN
FOR r IN (SELECT c,
rownum as rc,
dbms_lob.getlength(c) as totalchar
FROM mytable)
LOOP
-----------------Code for Rows starts--------------------------------------------------------------------------------
dbms_output.put_line('Row '||r.rc||' Started.');
dbms_output.put_line('Crossed Char counting query. TotalChar='||r.totalchar);
offset := 1;
WHILE (offset <= r.totalchar) LOOP
part := dbms_lob.substr(r.c, 20000, offset);
offset := offset + length(part);
dbms_output.put(part);
END LOOP;
dbms_output.put_line('');
END LOOP;
END;
/

Related

For loop not printing last record in a cursor

So,I am working with a cursor,the cursor was initially operating with the initial for loop,now i needed to perform operation if the no of records in the cursor is more than one,so i fetched the no of records first and stored in a variable and used an if-condition based on that.Now the problem is when I run the whole process,the procedure does its job,but only for the first record in the cursor and entirely skips the second record.Please suggest or help me identify the mistake.
Adding code snippet.
for m in get_m_p(a,b)--main cursor
loop
fetch get_m_p into c_m;
exit when g_m_p%notfound;
end loop;
tempcount := g_m_p%ROWCOUNT:
statements---
if(tempcount>1) then
statements----
end if;
end loop;
for the two records the main curosr is returning in first line,operations are only done for the first one,and the second record is being skipped entirely.
This is a superfluous line:
fetch get_m_p into c_m;
You don't explicitly fetch within a cursor FOR loop, it is implicitly done in each loop iteration. Remove that line.
How to get number of rows returned by a cursor? Lucky you, it seems that you don't care whether how many rows - exactly - it returns. All you want to know is whether it returned more than 1 row. So, count them, literally; exit the loop if counter exceeds 1.
SQL> DECLARE
2 CURSOR get_m_p IS
3 SELECT *
4 FROM emp
5 WHERE deptno = 10;
6
7 l_cnt NUMBER := 0;
8 BEGIN
9 FOR m IN get_m_p
10 LOOP
11 l_cnt := l_cnt + 1;
12 EXIT WHEN l_cnt > 1;
13 END LOOP;
14
15 DBMS_OUTPUT.put_line ('Cursor returned at least ' || l_cnt || ' row(s)');
16
17 IF l_cnt > 1
18 THEN
19 NULL;
20 -- the rest of statements go here
21 END IF;
22 END;
23 /
Cursor returned at least 2 row(s)
PL/SQL procedure successfully completed.
SQL>
As there's no way to know how many rows will cursor return, unfortunately, you'll have to check that first, and then decide what to do with the result.
DECLARE
CURSOR get_m_p IS
SELECT *
FROM emp
WHERE deptno = 10;
l_cnt NUMBER := 0;
BEGIN
SELECT COUNT (*)
INTO l_cnt
FROM (-- this is cursor's SELECT statement
SELECT *
FROM emp
WHERE deptno = 10);
FOR m IN get_m_p
LOOP
-- some statements here
IF l_cnt > 1
THEN
NULL;
-- statements to be executed if cursor return more than 1 row
END IF;
END LOOP;
END;
/
Cursor:
Oracle creates memory area to process SQL statement which is called context area and the cursor is pointer to the context area. A cursor holds the rows (one or more) returned by a SQL statement. The set of rows the cursor holds is referred to as the active set.
There are two type of cursor
1. Implicit cursor
2. Explicit cursor
Implicit Cursors :
Implicit cursors are automatically created by Oracle whenever an SQL statement is executed. Any SQL cursor attribute will be accessed as sql%attribute_name as shown below in the example. Use the SQL%ROWCOUNT attribute to determine the number of rows affected
DECLARE
no_of_records number(2);
BEGIN
select * from records;
IF sql%notfound THEN
dbms_output.put_line('no records present');
ELSIF sql%found THEN
no_of_records := sql%rowcount;
IF no_of_records > 1 THEN
dbms_output.put_line('no of records ' || no_of_records);
END IF
END IF;
END;
Explicit Cursors :
Explicit cursors are programmer-defined cursors for gaining more control over the context area. An explicit cursor should be defined in the declaration section of the PL/SQL Block. It is created on a SELECT Statement which returns more than one row.
Please see below example:
DECLARE
r_id records.id%type;
CURSOR c_records is
SELECT id FROM records;
BEGIN
OPEN c_records;
LOOP
FETCH c_records into r_id;
EXIT WHEN c_records%notfound;
dbms_output.put_line('Record id ' || r_id );
END LOOP;
CLOSE c_records;
END;
Reference :
https://www.tutorialspoint.com/plsql/plsql_cursors.htm
As an alternative you can cache every row and process after.
Example using sample schema "HR" on Oracle 11g Express Edition:
DECLARE
CURSOR get_m_p
IS
SELECT *
FROM hr.employees
WHERE department_id = 60
order by employee_id;
--
rcEmp_last get_m_p%rowtype;
l_cnt NUMBER;
BEGIN
FOR rcM IN get_m_p LOOP
l_cnt := get_m_p%rowcount;
Dbms_Output.Put_Line('l_cnt='||l_cnt);
if l_cnt=1 then
rcEmp_last:=rcM;
Else
Dbms_Output.Put_Line('Process='||to_char(l_cnt-1));
Dbms_Output.Put_Line('rcEmp_last.employee_id='||rcEmp_last.employee_id);
--
rcEmp_last:=rcM;
END IF;
End loop;
--
Dbms_Output.Put_Line('Exited FOR-LOOP');
Dbms_Output.Put_Line('l_cnt='||l_cnt);
--
if l_cnt>1 then
Dbms_Output.Put_Line('rcEmp_last.employee_id='||rcEmp_last.employee_id);
End if;
END;
Output:
Text
PL/SQL block, executed in 1 ms
l_cnt=1
l_cnt=2
Process=1
rcEmp_last.employee_id=103
l_cnt=3
Process=2
rcEmp_last.employee_id=104
l_cnt=4
Process=3
rcEmp_last.employee_id=105
l_cnt=5
Process=4
rcEmp_last.employee_id=106
Exited FOR-LOOP
l_cnt=5
rcEmp_last.employee_id=107
Total execution time 35 ms

If condition in PL/SQL script with cursor and loop

I would like to ask for some help or advice in this particular case.
I have table called "Teams". The table contains 3 columns - Issue, Responsible_team and More_Info (all varchar2).
I have a PL/SQL script with cursor and loop for selecting as many teams as issue description you type (some random word you think it might help you find the responsible team). This part works great for me.
But I do not know how to compile the IF condition in there. If no team is found according to typed word description, I would like to get some basic output dbms_output.put_line('Responsible team is not found').
There are 2 ways how I wrote the script. Classic loop and while loop.
I would be happy for any advice.
1.script
set verify off
DECLARE
v_issue teams.issue%type; --variable for issue column from teams table
v_respteam teams.responsible_team%type; --variable for responsible_team column from teams table
v_info teams.more_info%type; --variable for more_info column from teams table
--cursor declaration
CURSOR c_respteam
RETURN teams%ROWTYPE
IS
SELECT issue, responsible_team, more_info
FROM teams
WHERE lower(issue) like '%&Describe_Issue%';
BEGIN
OPEN c_respteam;
LOOP
FETCH c_respteam into v_issue, v_respteam, v_info;
EXIT when c_respteam%NOTFOUND;
dbms_output.put_line('Responsible team is '|| v_respteam || ' --> ' || v_info);
END LOOP;
CLOSE c_respteam;
end;
/
2.script
-- cursor with while loop
set verify off
DECLARE
v_issue teams.issue%type; --variable for issue column from teams table
v_respteam teams.responsible_team%type; --variable for responsible_team column from teams table
v_info teams.more_info%type; --variable for more_info column from teams table
CURSOR c_respteam
RETURN teams%ROWTYPE IS
SELECT issue, responsible_team, more_info
FROM teams
WHERE lower(issue) like '%&Describe_Issue%';
BEGIN
OPEN c_respteam;
FETCH c_respteam INTO v_issue, v_respteam, v_info;
WHILE c_respteam%FOUND
LOOP
dbms_output.put_line('Responsible team is '|| v_respteam || ' --> ' || v_info);
FETCH c_respteam INTO v_issue, v_respteam, v_info;
END LOOP;
CLOSE c_respteam;
END;
/
You could rewrite to:
declare
l_found boolean :=false;
cursor c_respteam is
select issue
,responsible_team
,more_info
from teams
where lower(issue) like '%&Describe_Issue%';
begin
for r in c_respteam
loop
l_found := true;
dbms_output.put_line('Responsible team is ' || r.responsible_team || ' --> ' || r.more_info);
end loop;
if not l_found
then
dbms_output.put_line('No records found');
end if;
end;
/
You need to have a counter variable [ETA: ooh, I like Rene's boolean variable idea instead; either way, you need an extra variable!] to work out if any rows were returned or not. I'm not sure why you're using an explicit cursor fetch, rather than using the cursor-for-loop? Cursor-for-loops are not only easier to write, read and maintain, but Oracle have put some behind-the-scenes optimisation in, to aid performance.
Of course, depending on what you're actually doing with the data returned by your cursor (dbms_output.put_line being something that you should never have in your production code), it's debatable that you would need to loop through a cursor at all.
Anyway, with that said, here's an example demonstrating how I would handle your requirement to check for no rows returned by the cursor:
declare
cursor cur (p_val varchar2)
is
select dummy
from dual
where dummy like '%'||p_val||'%';
v_counter integer := 0;
begin
for rec in cur('Y')
loop
dbms_output.put_line('value of dummy = '||rec.dummy);
v_counter := v_counter + 1;
end loop;
if v_counter = 0 then
dbms_output.put_line('no rows returned');
end if;
end;
/
no rows returned
declare
cursor cur (p_val varchar2)
is
select dummy
from dual
where dummy like '%'||p_val||'%';
v_counter integer := 0;
begin
for rec in cur('X')
loop
dbms_output.put_line('value of dummy = '||rec.dummy);
v_counter := v_counter + 1;
end loop;
if v_counter = 0 then
dbms_output.put_line('no rows returned');
end if;
end;
/
value of dummy = X
To expand on what I said in my comment below, it sounds like you just need a single sql statement, rather than using PL/SQL and relying on dbms_output.
Eg., say you have the following statement:
select lvl
from (select 'X'||level lvl from dual connect by level <= 10)
where lvl like '%&val%';
with &val blank, you get:
LVL
-----------------------------------------
X1
X2
X3
X4
X5
X6
X7
X8
X9
X10
With &val = 2 you get:
LVL
-----------------------------------------
X2
With &val = 100 you get:
no rows selected.

Using Rownum in Cursor Bulk Collect Oracle

I'm trying to use the rownum to simulate a column autonumbered as I need to use it as an ID. Since it is an ID, I look at the final table if no record with MAX (ID).
The problem I have is when I want to do arithmetic operations within the cursor or when you invoke, or when you want to use a function. The ROWNUM (v_id) field is empty me when I want to print with DBMS_OUTPUT . Anyone have any idea how to solve it without using sequences ?
Here put the sample code.
declare
max_id number;
CURSOR INSRT(w_max number) IS
SELECT f_max_fact_sap(to_number(V_ID),w_max) AS V_ID,Seriei,serief
FROM (SELECT To_Char(ROWNUM) AS V_ID, A.*
FROM (SELECT DISTINCT a.matnr, a.seriei, a.serief,a.xblnr,a.fecha_sap, ((SERIEF-SERIEI)+1) AS rango
FROM SOPFUN.TT_ZMOVIMI_FACTURADAS a
WHERE 0 =(SELECT COUNT(1)
FROM PA_ZMOVIMI_FACTURADAS B
WHERE A.SERIEI = B.SERIEI
AND A.SERIEF = B.SERIEF
AND A.MATNR = B.MATNR
AND A.FECHA_SAP=B.FECHA_SAP)
AND A.FECHA_SAP IS NOT NULL) A);
TYPE T_INSRT IS TABLE OF INSRT%ROWTYPE INDEX BY PLS_INTEGER;
V_INSRT T_INSRT;
begin
SELECT Max(Nvl(ID,10000)) INTO MAX_ID-- To Proof because the table is empty
FROM PA_ZMOVIMI_FACTURADAS;
OPEN INSRT(MAX_ID);
LOOP
FETCH INSRT BULK COLLECT INTO V_INSRT LIMIT 1000;
FOR I IN 1 .. V_INSRT.Count loop
DBMS_OUTPUT.PUT_LINE('ID: ' ||V_INSRT(I).V_ID||' SI: '||V_INSRT(I).SERIEI||' SI: '||V_INSRT(I).SERIEF||' OPERACION: '||to_char(f_max_fact_sap(V_INSRT(I).V_ID,MAX_ID)));
end loop;
EXIT WHEN INSRT%NOTFOUND;
END LOOP;
end;

bulk collect dynamic sql

I have to write a dynamic sql cursor where there are several possibilities in which the select query will be generated. Hence I am chosing dynamic and I am Using DBMS_SQL package to dynamically create a cursor and dynamically fetch the data.
However , Result set is going to be huge . around 11GB (there are 2.4 million records and the select statement will be approx 80 cols long assumning about 50Byte varchar per column)
Hence I cannot open the cursor at once . I want to know if there is a feature wherein i can fetch the data from the curosr keeping the curosr open for Blocks of say 1000 records at time(I will have to do this dynamically)
Please find the code attached which only fetches and prints the value of the columns (one sample case ) I want to use bul collect here \
Thanks
---------------code sample--------------------------------------
--create or replace type TY_DIMDEAL AS TABLE OF VARCHAR2(50) ;
create or replace procedure TEST_PROC (po_recordset out sys_refcursor)
as
v_col_cnt INTEGER;
v_ind NUMBER;
rec_tab DBMS_SQL.desc_tab;
v_cursor NUMBER;
lvar_output number:=0;
lvar_output1 varchar2(100);
lvar_output3 varchar2(100);
lvar_output2 varchar2(100);
LVAR_TY_DIMDEAL TY_DIMDEAL;
lvarcol varchar2(100);
begin
--
LVAR_TY_DIMDEAL := TY_DIMDEAL();
lvar_output1 := '';
v_cursor := dbms_sql.open_cursor;
dbms_sql.parse(v_cursor, 'select to_char(Field1) , to_char(fiel2) , to_char(field3) from table,table2 ', dbms_sql.native);
dbms_sql.describe_columns(v_cursor, v_col_cnt, rec_tab);
FOR v_pos in 1..rec_tab.LAST LOOP
LVAR_TY_DIMDEAL.EXTEND();
DBMS_SQL.define_column( v_cursor, v_pos ,LVAR_TY_DIMDEAL(v_pos),20);
END LOOP;
-- DBMS_SQL.define_column( v_cursor, 1 ,lvar_output1,20);
--DBMS_SQL.define_column( v_cursor, 2 ,lvar_output2,20);
--DBMS_SQL.define_column( v_cursor, 3 ,lvar_output3,20);
v_ind := dbms_sql.execute( v_cursor );
LOOP
v_ind := DBMS_SQL.FETCH_ROWS( v_cursor );
EXIT WHEN v_ind = 0;
lvar_output := lvar_output+1;
dbms_output.put_line ('row number '||lvar_output) ;
FOR v_col_seq IN 1 .. rec_tab.COUNT LOOP
LVAR_TY_DIMDEAL(v_col_seq):= '';
DBMS_SQL.COLUMN_VALUE( v_cursor, v_col_seq,LVAR_TY_DIMDEAL(v_col_seq));
dbms_output.put_line (LVAR_TY_DIMDEAL(v_col_seq));
END LOOP;
END LOOP;
end TEST_PROC;
Fetching data from a cursor in blocks of reasonable size, while keeping the cursor open, is one of PL/SQL Best Practices.
The above document (see Code 38 item) sketches an approach for when the select list is not known until runtime. Basically:
Define an appropriate type to fetch results into. Let's assume that all the returned columns will by of of type VARCHAR2:
-- inside DECLARE
Ty_FetchResults IS TABLE OF DBMS_SQL.VARCHAR2_TABLE;
lvar_results Ty_FetchResults;
Before each call to DBMS_SQL.FETCH_ROWS, call DBMS_SQL.DEFINE_ARRAY to enable batch fetching.
Call DBMS_SQL.FETCH_ROWS to fetch 1000 rows from the cursor.
Call DBMS_SQL.COLUMN_VALUE to copy the fetched data into your result array.
Process the results, record by record, in a FOR loop. Don't worry about the number of fetched records: if there are records to process, the FOR loop will run correctly; if the result array is empty, the FOR loop will not run.
Exit from the loop when the number of fetched records is less than the expected size.
Remember to DBMS_SQL.CLOSE the cursor.
Your loop body should look like this:
LOOP
FOR j IN 1..v_col_cnt LOOP
DBMS_SQL.DEFINE_ARRAY(v_cursor, j, lvar_results(j), 1000, 1);
END LOOP;
v_ind := DBMS_SQL.FETCH_ROWS(v_cursor);
FOR j IN 1..v_col_cnt LOOP
lvar_results(j).DELETE;
DBMS_SQL.COLUMN_VALUE(v_cursor, j, lvar_results(j));
END LOOP;
-- process the results, record by record
FOR i IN 1..lvar_results(1).COUNT LOOP
-- process a single record...
-- your logic goes here
END LOOP;
EXIT WHEN lvar_results(1).COUNT < 1000;
END LOOP;
-- don't forget: DBMS_CLOSE(v_cursor);
See also Doing SQL from PL/SQL: Best and Worst Practices.
LIMIT CLAUSE CAN COME TO RESCUE!
PL/SQL collections are essentially arrays in memory, so massive
collections can have a detrimental effect on system performance due to
the amount of memory they require. In some situations, it may be
necessary to split the data being processed into chunks to make the
code more memory-friendly. This “chunking” can be achieved using the
LIMIT clause of the BULK COLLECT syntax.
YOU CAN USE LIMIT CLAUSE AFTER BULK COLLECT INTO CLAUSE TO LIMIT YOUR RS.
AFTER YOU EXCEED TO LIMIT YOU CAN FETCH REMAINING ROWS.
SEE THIS ARTICLE
http://www.dba-oracle.com/plsql/t_plsql_limit_clause.htm

How to find number of rows in cursor

I would like to find the number of rows in a cursor. Is there a keyword that can help? Using COUNT, we have to write a query. Any help will be greatly appreciated.
The cursor_variable.%ROWCOUNT is the solution. But its value will be 0 if you check it after opening. You need to loop through all the records, to get the total row count. Example below:
DECLARE
cur sys_refcursor;
cur_rec YOUR_TABLE%rowtype;
BEGIN
OPEN cur FOR
SELECT * FROM YOUR_TABLE;
dbms_output.put_line(cur%rowcount);--returning 0
LOOP
FETCH cur INTO cur_rec;
EXIT WHEN cur%notfound;
dbms_output.put_line(cur%rowcount);--will return row number beginning with 1
dbms_output.put_line(cur_rec.SOME_COLUMN);
END LOOP;
dbms_output.put_line('Total Rows: ' || cur%rowcount);--here you will get total row count
END;
/
You must open the cursor and then fetch and count every row. Nothing else will work.
You can also use BULK COLLECT so that a LOOP is not needed,
DECLARE
CURSOR c
IS SELECT *
FROM employee;
TYPE emp_tab IS TABLE OF c%ROWTYPE INDEX BY BINARY_INTEGER;
v_emp_tab emp_tab;
BEGIN
OPEN c;
FETCH c BULK COLLECT INTO v_emp_tab;
DBMS_OUTPUT.PUT_LINE(v_emp_tab.COUNT);
CLOSE c;
END;
/
Edit: changed employee%ROWTYPE to c%ROWTYPE
You can use following simple single line code to print cursor count
dbms_output.put_line(TO_CHAR(cur%rowcount));
This should work for you
DECLARE
CURSOR get_data_ IS
SELECT *
FROM table_abc_
WHERE owner = user_; -- your query
counter_ NUMBER:= 0;
BEGIN
FOR data_ IN get_data_ LOOP
counter_ := counter_ + 1;
END LOOP;
dbms_output.put_line (counter_);
END;
DECLARE #STRVALUE NVARCHAR(MAX),
#CREATEDDATE DATETIME,
#STANTANCEVALUE NVARCHAR(MAX),
#COUNT INT=0,
#JOBCODE NVARCHAR(50)='JOB00123654',
#DATE DATETIME=GETDATE(),
#NAME NVARCHAR(50)='Ramkumar',
#JOBID INT;
CREATE TABLE #TempContentSplitValue (ITEMS NVARCHAR(200))
SELECT #JOBID = i.Id FROM JobHeader_TBL i WHERE Id=1201;
IF EXISTS (SELECT 1 FROM JobHeader_TBL WHERE Id=#JOBID)
BEGIN
SELECT #STRVALUE= Description from ContentTemplate_TBL where Id=1
INSERT INTO #TempContentSplitValue SELECT * FROM dbo.split(#STRVALUE, '_')
SET #STRVALUE=''
DECLARE db_contentcursor CURSOR FOR SELECT ITEMS FROM #TempContentSplitValue
OPEN db_contentcursor
FETCH NEXT FROM db_contentcursor
INTO #STANTANCEVALUE
WHILE (##FETCH_STATUS = 0)
BEGIN
SET #STRVALUE += #STANTANCEVALUE + 'JOB00123654'
SET #COUNT += 1
SELECT #COUNT
FETCH NEXT FROM db_contentcursor INTO #STANTANCEVALUE
END
CLOSE db_contentcursor
DEALLOCATE db_contentcursor
DROP TABLE #TempContentSplitValue
SELECT #STRVALUE
END
Here I am trying to count the total number of customers with age greater than 25. So store the result in the cursor first. Then count the size of the cursor inside the function or in the main begin itself.
DECLARE
cname customer24.cust_name%type;
count1 integer :=0;
CURSOR MORETHAN is
SELECT cust_name
FROM customer24
where age>25;
BEGIN
OPEN MORETHAN;
LOOP
FETCH MORETHAN into cname;
count1:=count1+1;
EXIT WHEN MORETHAN%notfound;
END LOOP;
-- dbms_output.put_line(count1);
dbms_output.put_line(MORETHAN%ROWCOUNT);
CLOSE MORETHAN;
END;
There is a possible work around that may be useful/needed because of the overhead of accessing a database server over a network (e.g., when using Ajax calls)
Consider this:
CURSOR c_data IS
SELECT per_first_name , null my_person_count
FROM person
UNION
SELECT null as per_first_name , count( distinct per_id ) as my_person_count
FROM person
order by my_person_count ;
The first row fetched has the count of records. One MUST add specific columns fetched (the use of the * does not work), and one can add additional filters.
Try this:
print(len(list(cursor)))
I always read that people loop through results. Why not using a count(*)?
An example from my production code:
PROCEDURE DeleteStuff___(paras_ IN Parameters_Type_Rec)
IS
CURSOR findEntries_ IS
select * from MyTable
where order_no = paras_.order_no;
counter_ NUMBER;
CURSOR findEntries_count_ IS
SELECT COUNT(*) from MyTable
where order_no = paras_.order_no;
BEGIN
OPEN findEntries_count_;
FETCH findEntries_count_ INTO counter_;
CLOSE findEntries_count_;
dbms_output.put_line('total records found: '||counter_);
IF (counter_ = 0) THEN
-- log and leave procedure
RETURN;
END IF;
FOR order_rec_ IN findEntries_ LOOP
EXIT WHEN findEntries_%NOTFOUND OR findEntries_%NOTFOUND IS NULL;
-- do stuff - i.e. delete a record.
API_Package.Delete(order_rec_);
END LOOP;
END DeleteStuff___;
If the query is small, that is my prefered way.
In this example, I just want to know (and log) how many entries I'll delete.
p.s. Ignore the three underlines. In IFS, this is used when you want private procedures or functions.
You can’t have cursor count at start. For that you need to fetch complete cursor; that is the way get cursor count.
declare
cursor c2 is select * from dept;
var c2%rowtype;
i number :=0;
begin
open c2;
loop
fetch c2 into var;
exit when c2%NOTFOUND;
i: = i+1;
end loop;
close c2;
dbms_output.put_line('total records in cursor'||i);
end;
You can use %ROWCOUNT attribute of a cursor.
e.g:
DECLARE
CURSOR lcCursor IS
SELECT *
FROM DUAL;
BEGIN
OPEN lcCursor ;
DBMS_OUTPUT.PUT_LINE(lcCursor%ROWCOUNT);
CLOSE lcCursor ;
END;

Resources