Выполняем код для каждой строки в выборке Transact SQL с использованием курсора

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

  1. Создаем курсор, описывая выборку, со строками которой мы будем работать. Запрос может быть сколь угодно сложным, с кучей JOIN
  2. Открываем курсор
  3. Объявляем переменные, в которые будем выбирать поля каждой строки, количество переменных должно совпадать с количеством столбцов в запросе
  4. Делаем выборку первой строки
  5. Прокручиваем в цикле наш код, завершая его выборкой следующей строки
  6. Закрываем курсор

-- обьявляем курсор 
declare some_cursor cursor
--- sql запрос любой сложности, формирующий набор данных для курсора
for 
  select SOME_INT_FIELD, SOME_VARCHAR_FIELD from SOME_TABLE
-- открываем курсор
open some_cursor
-- курсор создан, обьявляем переменные и обходим набор строк в цикле
declare  @counter int
declare  @int_var int, @string_var varchar(100) 
set @counter = 0
-- выборка первой  строки
fetch next from some_cursor INTO  @int_var, @string_var
-- цикл с логикой и выборкой всех последующих строк после первой
while @@FETCH_STATUS = 0
begin
--- логика внутри цикла
set @counter = @counter + 1
 if @counter >= 5 break  -- возможный код для проверки работы, прерываем после пятой итерации

-- отладочный select, на большом количестве строк выборка данных  в  sql server management studio может привести к ошибке переполнения памяти
SELECT @int_var, @string_var
INSERT INTO OTHER_TABLE (SOME_FIELD1, SOME_FIELD2) VALUES (@string_var, 'Мегастрока')
DELETE FROM OTHER_TABLE2 WHERE ID_FIELD =  @int_var
exec some_stored_procedure
-- выборка следующей строки
fetch next from some_cursor INTO  @int_var, @string_var
-- завершение логики внутри цикла
end
select @counter as final_count
-- закрываем курсор
close some_cursor
deallocate some_cursor

Курсоры (Transact-SQL)
FETCH (Transact-SQL)
@@FETCH_STATUS (Transact-SQL)


Комментарии

Выполняем код для каждой строки в выборке Transact SQL с использованием курсора — 1 комментарий

Добавить комментарий для Анатолий Отменить ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *


*

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>