Подтвердить что ты не робот

TSQL - выполнить код для каждой строки выбранного

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

В моем случае: У меня есть временная таблица для хранения некоторых данных для complexe script. В конце я хочу вывести некоторую информацию этой таблицы (ограниченную некоторыми условиями) на выход.

В настоящее время я использую курсор с выделенным для ограничения строк таблицы. В этом курсоре я использую

 print '...'

для генерации вывода.

Должен быть более простой способ делать такие вещи...

изменить:

create table #tmpAttributes(AttributeId uniqueidentifier, Value float, ValueString nvarchar(max), ActionId uniqueidentifier)

insert into #tmpAttributes (AttributeId, Value, ValueString, ActionId)
    select ID,..... -- in this select i'm doing some value conversions, if conversion is not possible i'm using -1

insert into ActionAttribute (ActionDefinitionID, Discriminator, ID, ReferredActionID, ValueDate, ValueListID, ValueMoney, ValueString, ValueUserID)
    select @defId, 'ActionAttributeMoneyEntity', NEWID(), ActionId, null, null, Value, null, null from #tmpAttributes

-- afterwards there is this cursor where I'm printint all rows where Value = -1
4b9b3361

Ответ 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). Поскольку временная таблица не обновляется во время каждой итерации цикла, я бы ожидал, что она будет быстрее.

Ответ 2

Я думаю, вам нужно предоставить более подробную информацию, но вы можете найти что-то вроде:

declare @msg varchar(max)='';

select @msg = @msg + 'Output line: ' + ColumnA + ' -- ' + 'ColumnB' + char(13)+char(10)
from #temp
where ...
;

print @msg;