Есть ли способ получить список открытых / выделенных курсоров в SQL-сервере? - PullRequest
5 голосов
/ 05 ноября 2008

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

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

Ответы [ 5 ]

2 голосов
/ 23 апреля 2013

Работает на 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
2 голосов
/ 05 ноября 2008

Смотрите здесь для получения информации о том, как найти курсоры. Я никогда не использовал ни одного из них, потому что я мог придумать способ сделать это, не переходя Row By Agonizing Row.

Вы должны перестроить sp в

  • не использовать курсоры (мы можем помочь - почти всегда есть способ избегать RBAR)

  • встроить его в транзакцию и откатить его в случае сбоя или при обнаружении ошибки. Вот несколько отличных статей на эту тему. часть 1 и часть 2

Если у вас SQL2005, вы также можете использовать try catch

РЕДАКТИРОВАТЬ (в ответ на ваше сообщение): в идеале генерация данных лучше всего обрабатывать на уровне приложений, поскольку они лучше подходят для операций, не основанных на множествах.

Red Gate имеет Генератор данных SQL , который я использовал ранее (отлично подходит для отдельных таблиц, но требует некоторой настройки, если у вас много FK или широкая [нормализованная] база данных).

1 голос
/ 10 ноября 2008

Мне кажется, это работает:

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
0 голосов
/ 08 августа 2018

Вы можете использовать

sys.dm_exec_cursors

как описано здесь

По сути, вы можете запустить этот пример запроса и получить информацию о курсорах, открытых в различных базах данных

sys.dm_exec_cursors (0)

0 голосов
/ 15 января 2013

Вы можете использовать системную хранимую процедуру sp_cursor_list , чтобы получить список курсоров, видимых для текущего соединения, и sp_describe_cursor , sp_describe_cursor_columns и sp_describe_cursor_tables для определения характеристик курсор.

(из http://msdn.microsoft.com/it-it/library/aa172595(v=sql.80).aspx)

...