5. Working with a Database : How You Can Access a Database with Standard SQL Statements : How You Can Use Cursors to Access the Database
 
Share this page                  
How You Can Use Cursors to Access the Database
Cursors are useful for:
Bringing only part of a result set across the network where low communications bandwidth is an issue
Performing an unrelated operation in the midst of processing returned rows (which can also be performed using a select loop)
Performing operations on returned values that span two or more event blocks
Determining which of several select statements in a fetch loop to execute at runtime, for example:
if frame_mode = MODE_SALES then
   open cursor1 for select salesname as name,
      salesquota as amount
      from sales where region = :region order
      by amount;
elseif frame_mode = MODE_MGRS then
   open cursor1 for select mgrname as name,
      budget as amount from managers
      where business_unit = :bus_unit
      order by name;
else
   open cursor1 for select staffname as name,
      salary as amount
      from staff where staff_code = :staff_code
      ORDER BY Amount;
endif;
i = 0;
curs_state = CS_CURRENT;
while (curs_state = CS_CURRENT) do
   i = i + 1;
   fetch cursor1 into :tf[i].name = name,
      :tf[i].amount = amount;
      curs_state = cursor1.state;
endwhile;
/* number of rows fetched = i-1 */
close cursor1;
Providing better performance than a select loop when the application plans to limit the number of rows selected
Select loops cache every row that qualifies for the select. Setting DBSessionObject's PreFetchRow attribute when using a read-only cursor lets you limit the number of qualifying rows actually fetched.
For example, suppose you want to fill a tablefield with the top 10 salespeople (by sales) from a particular region. Using a select loop, you would code:
i = 1;
select :tf[i].name = name, :tf[i].quota = quota,
    :tf[i].sales = sales
    from salespeople where region = :region
    order by sales desc
    {
        i = i + 1;
        if i > 10 then
        endloop;
        endif;
    }
This technique is inefficient because all salespeople rows for the specified region are returned to OpenROAD from the database when only 10 are desired. The following example is a more efficient way to code this situation:
CurFrame.DBsession.PrefetchRows = 10;
open cursor1 for select name as name,
quota as quota,
sales as sales
from salespeople where region = :region
order by sales desc for readonly;
i = 0;
curs_state = CS_CURRENT;
while (curs_state = CS_CURRENT) do
i = i + 1;
fetch cursor1 into :tf[i].name = name,
    :tf[i].quota = quota, :tf[i].sales =
        sales;
curs_state = cursor1.state;
if i > 10 then
    endloop;
endif;
endwhile;
/* number of rows fetched = i-1 */
close cursor1;
The PreFetchRows attribute enables you to tune the performance of cursors when you have an approximate idea of the number of rows the cursor will return.