Курсор TSQL, как проверить, если уже объявлен и, следовательно, освободить - PullRequest
6 голосов
/ 05 января 2012

Как я могу убедиться, что освободил курсор, если он уже существует, прежде чем пытаться открыть его снова?

Для таблицы я могу использовать что-то вроде:

if exists (select top 1 from tempdb.sys.tables where name = '##tmpTable') 
    drop table ##tmpTable;  
... then I can recreate my ##tmpTable 

Но я не могу понять, как это сделать для курсора типа

-- First clean up if already exists..
  .....                                  <----- what goes here???

-- Declare and use a cursor
DECLARE  someCursorName CURSOR 
 FOR 
  select something from somewhere
 FOR READ ONLY

Я делаю это, чтобы убедиться, что мой скрипт очищается, прежде чем он начнет работать

Лучшее, что я могу придумать, это:

begin try DEALLOCATE someCursorName ; end try begin catch end catch

Это хорошая практика?

EDIT: Это сценарий обслуживания. В наших специализированных клиентских базах данных может быть много таблиц, и курсор используется для статистического анализа таблиц - в зависимости от типов таблиц могут происходить разные вещи. В основном много динамического sql. Если скрипт не удастся, я бы хотел повторить работу, не беспокоясь о ручном вмешательстве. Здесь есть только один уровень охвата.

Как и все, я рад заменить курсоры операциями над множествами. Вот что делают циклы курсора:

  • создание sql для реорганизации / перестроения индексов (изначально был ручной sql для определения DDL для запуска, а затем был выдан DDL)
  • анализировать разброс данных и ошибки в разных таблицах
  • поиск ошибок в журналах, поиск соответствующих таблиц и получение этих данных (изначально был ручной sql, чтобы определить места, где были ошибки, а затем вырезать и вставлять шаблон (ы) для поиска ошибок, зависящих от типов ошибка)

1 Ответ

7 голосов
/ 05 января 2012

Вы можете объявить Курсор как переменную, тогда он будет закрыт и автоматически освобожден , когда он выйдет из области видимости. Пример использования этого в сочетании с динамическим SQL приведен ниже.

DECLARE @C1 AS CURSOR;

SET @C1 = CURSOR FAST_FORWARD
FOR SELECT name
    FROM   master..spt_values
    WHERE  name <> ''
    ORDER  BY name;

OPEN @C1;

EXEC sp_executesql N'
DECLARE @name VARCHAR(50)
FETCH NEXT FROM @C1 INTO @name;

WHILE @@FETCH_STATUS = 0
  BEGIN
      PRINT @name

      FETCH NEXT FROM @C1 INTO @name;
  END 
', N'@C1 CURSOR', @C1 = @C1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...