У меня есть хранимая процедура, которая создает и открывает некоторые курсоры. Он закрывает их в конце, но если возникает ошибка, курсоры остаются открытыми! Затем последующие запуски завершаются неудачно, когда он пытается создать курсоры, поскольку курсор с таким именем уже существует.
Есть ли способ узнать, какие курсоры существуют и открыты они или нет, чтобы я мог закрыть и освободить их? Мне кажется, это лучше, чем слепые попытки закрыть и проглотить ошибки.


Смотри сюда для информации о том, как найти курсоры. Я никогда не использовал ни один из них, потому что я мог придумать способ сделать это, не переходя «Строка за агонизирующей строкой».
Вам следует перестроить sp, чтобы
не использовать курсоры (мы можем помочь - почти всегда есть способ избегать RBAR)
встроите его в транзакцию и откатите, если произойдет сбой или вы обнаружите ошибку. Вот несколько отличных статей по этому поводу. часть 1 и часть 2
Если у вас есть SQL2005, вы также можете использовать попробуй поймать
РЕДАКТИРОВАТЬ (в ответ на ваше сообщение): в идеале создание данных лучше всего обрабатывать на уровне приложения, поскольку они лучше подходят для операций, не основанных на наборах.
Red Gate имеет Генератор данных SQL, который я использовал раньше (он отлично подходит для отдельных таблиц, но требует некоторой настройки, если у вас много FK или широкая [нормализованная] база данных).
Мне кажется, это работает:
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
You can use the sp_cursor_list system stored procedure to get a list of cursors visible to the current connection, and sp_describe_cursor, sp_describe_cursor_columns, and sp_describe_cursor_tables to determine the characteristics of a cursor.
(из http://msdn.microsoft.com/it-it/library/aa172595(v=sql.80).aspx)
Это работает на 2008R2, раньше ни на чем не тестировался:
USE MASTER
GO
select s.session_id, s.host_name, s.program_name, s.client_interface_name, s.login_name
, c.cursor_id, c.properties, c.creation_time, c.is_open, con.text,
l.resource_type, d.name, l.request_type, l.request_Status, l.request_reference_count, l.request_lifetime, l.request_owner_type
from sys.dm_exec_cursors(0) c
left outer join (select * from sys.dm_exec_connections c cross apply sys.dm_exec_sql_text(c.most_recent_sql_handle) mr) con on c.session_id = con.session_id
left outer join sys.dm_exec_sessions s on s.session_id = c.session_id
left outer join sys.dm_tran_locks l on l.request_session_id = c.session_id
left outer join sys.databases d on d.database_id = l.resource_database_id
Вы можете использовать
sys.dm_exec_cursors
как описано здесь
По сути, вы можете запустить этот пример запроса и получить информацию о курсорах, открытых в различных базах данных.
sys.dm_exec_cursors(0)