2008-11-05 9 views
5

Tengo un procedimiento almacenado que crea y abre algunos cursores. Los cierra al final, pero si se produce un error, ¡esos cursores se dejan abiertos! Luego las siguientes ejecuciones fallan cuando intenta crear cursores ya que un cursor con el nombre ya existe.¿Hay alguna manera de obtener una lista de cursores abiertos/asignados en el servidor SQL?

¿Hay alguna manera de que pueda consultar qué cursores existe y si están abiertos o no, así que puedo cerrarlos y desasignarlos? Siento que esto es mejor que ciegamente tratando de cerrar y tragar los errores.

Respuesta

1

Esto parece funcionar para mí:

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 '[email protected] 

    IF @cursorStatus > -3 
     SET @sql = @sql+' DEALLOCATE '[email protected] 

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

END 
2

Look here para obtener información sobre cómo encontrar los cursores. Nunca he usado ninguno de ellos porque podría encontrar una manera de hacerlo sin ir a Row By Agonizing Row.

Debe reconstruir el sp a cualquiera

  • no utilizar los cursores (podemos ayudar - casi siempre existe una manera de evitar RBAR)

  • construirla en una transacción y rollo volver si hay una falla o si detecta un error. Aquí hay algunos excelentes artículos sobre esto. part 1 y part 2

Si tiene SQL2005, también se puede utilizar try catch

EDITAR (en respuesta a su puesto): Idealmente, la generación de datos se maneja mejor a nivel de aplicación, ya que son más adecuados para operaciones no basadas en conjuntos.

Red Gate tiene un SQL Data generator que he usado anteriormente (es ideal para una sola tabla, pero requiere algo de configuración si tiene muchos FK o una base de datos amplia [normalizada]).

2

Esto funciona en 2008R2, no se han probado en cualquier cosa antes que eso:

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 
Cuestiones relacionadas