Ответ 1
Выполнение оператора печати для каждой строки в наборе результатов в значительной степени требует использования курсора или подхода, подобного этому
declare @id int, @stuff varchar(20)
declare @tmp table
(
id int not null
, stuff varchar(20)
primary key(id)
)
insert @tmp
select id, stuff from mastertable
where condition1 > condition2
select top 1 @id=id, @stuff=stuff from @tmp
while (@@rowcount > 0)
begin
print @stuff
delete from @tmp where [email protected]
select top 1 @id=id, @stuff=stuff from @tmp
end
Вы по-прежнему перебираетесь по каждой строке, но избегаете курсора. Поскольку вы используете таблицу var вместо курсора, вы избегаете блокировки таблицы, но это не обязательно лучший подход. Вы можете обрабатывать строки за строкой различными способами, такими как добавление "обработанного столбца" или нумерация всех выбранных строк 1..n и итерация на основе номера журнала
Вы можете избежать обработки строк за строкой, если вы можете выполнять операцию на основе набора. В вашем вопросе недостаточно информации о том, можно ли избежать этого в TSQL
Теперь запись CLR-proc может быть более гибкой, так как у вас намного более богатая модель программирования, и для каждой строки набора результатов в CLR-процессе есть небольшие накладные расходы. Выполнение вызова базы данных из proc CLR для каждой строки, вызываемой вызовом базы данных из каждой строки в TSQL
EDIT. Я вижу, что кто-то уже добавил один из возможных способов преобразования ваших заявлений печати в операцию, ориентированную на набор. то есть.
declare @msg varchar(max)
select @msg = ''
select msg = @msg + stuff
from mastertable where condition1 > condition2
print @msg
Это нормально, на самом деле оптимально, что я имел в виду, когда сказал, что выполняю операцию установки. Операция, основанная на наборе, всегда предпочтительнее, когда это возможно. Это может быть не очевидно, но конкатенация строк также может быть очень медленной в этом примере, если задействовано много строк.
Я сказал, что использование temp var позволяет избежать блокировки таблицы. Это не совсем так, поскольку SQL-сервер записывает temp vars в таблицу в tempdb. Я действительно имел в виду, что вы избегаете блокировки производственной таблицы, и поскольку вы гарантированно являетесь единственным пользователем этой таблицы, вы не будете конкурировать за одновременный доступ.
Я также не пытался оптимизировать это. Например, внутренний цикл может отслеживать идентификатор, а условие where становится id > @id (вам также нужен первичный ключ, определенный на id). Поскольку временная таблица не обновляется во время каждой итерации цикла, я бы ожидал, что она будет быстрее.