Link to home
Start Free TrialLog in
Avatar of TimFred
TimFred

asked on

Can I convert a cursor to a "Fire Hose" Cursor in my stored procedure?

I have a stored procedure with many cursors in it. Sometimes it runs for 5-7minutes. Rather than re-writing thte stored proc. I would like to change the cursors to act as a "Fire Hose Cursor". I found an article on MSDN about server side cursors and firehose cursors and they said that:  It turns out that ODBC determines whether a server cursor or a Default Result Set should be used during prepare/execute time. If the multiple array binding happens before prepare/execute (row array size > 1), server cursor is used by ODBC. It could even re-prepare if the binding with array size > 1 is left before the next execute. So the solution is to temporarily set the row array size to 1 before the prepare/execute/re-execute and reset it back to the >1 value before fetching. That way, you get a fire hose cursor and the block-fetch behavior.

The following is a sample of one of my cursors(I did not paste the whole thing in here, it actually goes on for 207 fields):

DECLARE cur_total CURSOR FOR
            SELECT distinct r, person_id, inst_id, identity_id
            FROM #temp
            
            OPEN cur_total
            FETCH cur_total INTO @r, @person_id2, @instid2, @identity_id
            
            WHILE (@@fetch_status = 0) BEGIN

DECLARE cur_fields CURSOR FOR
   SELECT DISTINCT field_order, field_name
   FROM #temp
   where person_id = @person_id2
   and   r = @r
   and inst_id = @instid2
   and identity_id = @identity_id
   order by field_order, field_name

   OPEN cur_fields
   FETCH cur_fields INTO @field_order, @field_name
 
   IF (@@fetch_status = 0) BEGIN
         UPDATE #done
         SET field1_name = @field_name,
             field1_value = (select field_value
                         FROM #temp t
                         WHERE t.field_name = @field_name AND t.person_id = @person_id2
                and   t.r = @r and t.inst_id = @instid2 and t.identity_id = @identity_id)
    where person_id = @person_id2
    and   r = @r
    and inst_id = @instid2
    and counter = @identity_id
   END
   
 FETCH cur_fields INTO @field_order, @field_name

   IF (@@fetch_status = 0) BEGIN
         UPDATE #done
         SET field2_name = @field_name,
             field2_value = (select field_value
                         FROM #temp t
                         WHERE t.field_name = @field_name AND t.person_id = @person_id2
                 and   t.r = @r and t.inst_id = @instid2 and t.identity_id = @identity_id)
    where person_id = @person_id2
    and   r = @r
    and inst_id = @instid2
    and counter = @identity_id
   END
   
CLOSE cur_fields
  deallocate cur_fields

FETCH cur_total INTO @r, @person_id2, @instid2, @identity_id
                     
               END


CLOSE cur_total
  deallocate cur_total



Is there some way I can convert my cursor code so that it operates as a "fire hose" cursor?  Maybe by incorporating:

// set row array size to 1 just before execute
 
(SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)1, 0);

  // set row array size to > 1 just before fetch
 (SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)ROW_ARRAY_SIZE, 0);

Please let me know if something like this is possible?


Avatar of Lowfatspread
Lowfatspread
Flag of United Kingdom of Great Britain and Northern Ireland image

Hello TimFred,

the server side cursor processing is for the result sets returned by a stored procedure it has nothing to do with the
internal cursors within the stored procedure itself...
 
a brief examination of your code leads me to believe that this cursor is not required...
and should be replace by pure update statements with joins to the tables in question.

a re-design of your stored procedure is the best way forward.

Regards,

Lowfatspread
The "Server Side" and "Firehose" Cursors that ODBC uses are not the same thing as the Cursor declared in your Stored Procedure.

The ODBC Cursors deal with the resultset returned from your stored procedure after the stored procedure has completed.

So, if your stored procedure takes 5 minutes to execute, nothing you do in VB is going to speed that up.

So First, the obligatory moral statement:  Do NOT use CURSORS in SQL.  Try to rewrite your SP into something set based.

If it turns out that you really need to do this row by agonizing row, create your recordsets in VB and do the processing there instead of in SQL.

--
JimFive
Avatar of TimFred
TimFred

ASKER

Lowfatspread,

Can you give me an example of how you would convert the cursor example I gave to an update statement?

Thanks!
ASKER CERTIFIED SOLUTION
Avatar of JimFive
JimFive
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of TimFred

ASKER

please take a look at this article and let me know if I can implement this to speed up my cursors:

http://blogs.msdn.com/mssqlisv/archive/2006/03/24/560386.aspx
No, your problem is with SQL Cursors not ODBC Cursors.
--
JimFive