Esiste un modo per ottenere un elenco di cursori aperti / allocati in SQL Server?
-
06-07-2019 - |
Domanda
Ho una procedura memorizzata che crea e apre alcuni cursori. Li chiude alla fine, ma se colpisce un errore quei cursori rimangono aperti! Quindi le esecuzioni successive falliscono quando tenta di creare cursori poiché esiste già un cursore con il nome.
Esiste un modo in cui posso interrogare quali cursori esistono e se sono aperti o no in modo da poterli chiudere e deallocare? Sento che è meglio che cercare ciecamente di chiudere e ingoiare errori.
Soluzione 3
Questo sembra funzionare per 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
Altri suggerimenti
Guarda qui per informazioni su come per trovare i cursori. Non ho mai usato nessuno di loro perché sono riuscito a trovare un modo per farlo senza andare a Rowon Agonizing Row.
Dovresti ricostruire lo sp in
-
non usare i cursori (possiamo aiutarti - c'è quasi sempre un modo per evitare RBAR)
-
compilalo in una transazione e ripristinalo in caso di errore o se rilevi un errore. Ecco alcuni articoli eccellenti su questo. part 1 e parte 2
Se hai SQL2005, puoi anche usare provare a catturare
EDIT (in risposta al tuo post): idealmente, la generazione dei dati è gestita al meglio a livello di applicazione in quanto sono più adatti per operazioni non basate su set.
Red Gate ha un Generatore di dati SQL che ho usato prima (è ottimo per le singole tabelle, ma richiede alcune configurazioni se si dispone di un sacco di FK o di un ampio database [normalizzato]).
Funziona su 2008R2, non ho testato nulla prima:
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
Puoi usare la sp_cursor_list stored procedure di sistema per ottenere un elenco di cursori visibili alla connessione corrente e sp_describe_cursor , sp_describe_cursor_columns e sp_describe_cursor_tables per determinare le caratteristiche di a cursore.
(da http://msdn.microsoft .com / it-it / library / aa172595 (v = sql.80) .aspx )
Puoi usare
sys.dm_exec_cursors
come descritto qui
Fondamentalmente è possibile eseguire questa query di esempio e ottenere informazioni sui cursori aperti in vari database
sys.dm_exec_cursors (0)