Курсор - это механизм в SQL, который позволяет построчно обрабатывать результаты запроса, а не работать со всем результирующим набором сразу. Это объект базы данных, который предоставляет возможность последовательного доступа к строкам результирующего набора с возможностью модификации данных.
Основные характеристики курсоров
- Построчная обработка - обращение к данным строка за строкой
- Позиционирование - возможность перемещаться по результирующему набору
- Модификация - изменение данных "на лету" при необходимости
- Состояние - запоминание текущей позиции в наборе данных
Типы курсоров в SQL Server
1. По области видимости
- Локальные (LOCAL) - видимы только в текущей сессии/процедуре
- Глобальные (GLOBAL) - видимы во всех сессиях
2. По способу обновления
- Статические (STATIC) - "снимок" данных на момент создания
- Динамические (DYNAMIC) - отражают изменения в реальном времени
- Ключевые (KEYSET) - фиксированный набор ключей, но изменяемые данные
- Быстрые последовательные (FAST_FORWARD) - оптимизированы для быстрого чтения вперед
3. По направлению обхода
- Однонаправленные (FORWARD_ONLY) - только последовательное чтение
- Прокручиваемые (SCROLL) - возможность перемещения в любом направлении
Синтаксис создания курсора
DECLARE cursor_name CURSOR
[LOCAL | GLOBAL]
[FORWARD_ONLY | SCROLL]
[STATIC | KEYSET | DYNAMIC | FAST_FORWARD]
[READ_ONLY | SCROLL_LOCKS | OPTIMISTIC]
FOR select_statement
[FOR UPDATE [OF column_list]]
Пример использования курсора
DECLARE @EmployeeID INT, @EmployeeName NVARCHAR(100)
DECLARE employee_cursor CURSOR FOR
SELECT EmployeeID, FullName FROM Employees WHERE Department = 'IT'
OPEN employee_cursor
FETCH NEXT FROM employee_cursor INTO @EmployeeID, @EmployeeName
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'Обработка сотрудника: ' + @EmployeeName
-- Логика обработки каждой строки
UPDATE EmployeeStats
SET LastProcessed = GETDATE()
WHERE EmployeeID = @EmployeeID
FETCH NEXT FROM employee_cursor INTO @EmployeeID, @EmployeeName
END
CLOSE employee_cursor
DEALLOCATE employee_cursor
Когда использовать курсоры
- Последовательная обработка строк с сложной бизнес-логикой
- Каскадные обновления связанных таблиц
- Построчная валидация данных
- Миграции данных с преобразованиями
Проблемы и ограничения курсоров
- Производительность - значительно медленнее, чем set-based операции
- Блокировки - могут удерживать ресурсы длительное время
- Память - потребляют дополнительные ресурсы сервера
- Сложность сопровождения - код с курсорами часто сложнее для понимания
Альтернативы курсорам
- Set-based операции - WHERE, JOIN, GROUP BY и т.д.
- Оконные функции - ROW_NUMBER(), LEAD(), LAG() и др.
- Временные таблицы - с последующей пакетной обработкой
- CTE (Common Table Expressions) - для рекурсивных запросов
Рекомендации по использованию
- Избегайте курсоров, где возможно использовать set-based подход
- Выбирайте правильный тип курсора под задачу
- Всегда освобождайте ресурсы (CLOSE + DEALLOCATE)
- Ограничивайте размер выборки для курсора
- Используйте FAST_FORWARD для простых операций чтения
Резюмируем
Курсор - это мощный, но ресурсоемкий инструмент SQL Server для:
- Построчной обработки данных
- Сложных последовательных операций
- Сценариев, где set-based подход неприменим
Хотя курсоры предоставляют гибкость, они должны использоваться осмотрительно, так как могут значительно снижать производительность. В большинстве случаев операции над множествами (set-based) предпочтительнее.