views:

351

answers:

3

I have a stored procedure that creates and opens some cursors. It closes them at the end, but if it hits an error those cursors are left open! Then subsequent runs fail when it tries to create cursors since a cursor with the name already exists.

Is there a way I can query which cursors exists and if they are open or not so I can close and deallocate them? I feel like this is better than blindly trying to close and swallow errors.

+2  A: 

Look here for info on how to find cursors. I have never used any of them because I could figure out a way to get it done without going Row By Agonizing Row.

You should rebuild the sp to either

  • not use cursors ( we can help - there is almost always a way to avoid RBAR)

  • build it in a transaction and roll it back if there is a failure or if you detect an error. Here are some excellent articles on this. part 1 and part 2

If you have SQL2005, you can also use try catch

EDIT (in response to your post):Ideally, data generation is best handled at the application level as they are better suited for non set based operations.

Red Gate has a SQL Data generator that I have used before (its great for single tables, but takes some configuring if you have lots of FK or a wide [normalized] database).

StingyJack
A: 

Thanks for the reply, I will be sure to check out that link! The reason I am going RBAR is because I am trying to generate some test data and am permuting over various settings. I know I could so some cross joins but I want the rand() function called multiple times so I get different values for my rows.

Sadly this machine is SQL Server 2000.

Zugwalt
You should add this to the comments of of the reply so others can know who you are targeting, or to your original post as an edit so its easier for others to understand.
StingyJack
There was a 300 character limit :-(
Zugwalt
A: 

This seems to work for me:

CREATE PROCEDURE dbo.p_cleanUpCursor @cursorName varchar(255) AS
BEGIN

    DECLARE @cursorStatus int
    SET @cursorStatus =  (SELECT cursor_status('global',@cursorName))

    DECLARE @sql varchar(255)
    SET @sql = ''

    IF @cursorStatus > 0
     SET @sql = 'CLOSE '+@cursorName

    IF @cursorStatus > -3
     SET @sql = @sql+' DEALLOCATE '+@cursorName

    IF @sql <> ''
     exec(@sql)

END
Zugwalt