Как мне избежать использования курсоров в Sybase (T-SQL)?
Вопрос
Представьте себе сцену: вы обновляете какой-то устаревший код Sybase и натыкаетесь на курсор.Хранимая процедура создает результирующий набор в таблице #temporary, которая полностью готова к возврату, за исключением того, что один из столбцов не очень удобочитаем для человека, это буквенно-цифровой код.
Что нам нужно сделать, так это выяснить возможные различные значения этого кода, вызвать другую хранимую процедуру для перекрестной ссылки на эти скрытые значения, а затем обновить результирующий набор новыми расшифрованными значениями:
declare c_lookup_codes for
select distinct lookup_code
from #workinprogress
while(1=1)
begin
fetch c_lookup_codes into @lookup_code
if @@sqlstatus<>0
begin
break
end
exec proc_code_xref @lookup_code @xref_code OUTPUT
update #workinprogress
set xref = @xref_code
where lookup_code = @lookup_code
end
Итак, хотя у некоторых людей это может вызвать учащенное сердцебиение, это действительно работает.Мой вопрос в том, как лучше всего избежать подобных вещей?
_NB:для целей этого примера вы также можете представить, что результирующий набор находится в области 500 тыс. строк и что существует 100 различных значений look_up_code и, наконец, что невозможно создать таблицу со значениями внешних ссылок, поскольку логика в proc_code_xref слишком запутанна._
Решение
У вас должна быть таблица внешних ссылок, если вы хотите убрать курсор.Предполагая, что вы знаете 100 различных значений подстановки (и что они статичны), несложно сгенерировать одно из них, вызвав proc_code_xref 100 раз и вставив результаты в таблицу
Другие советы
Если вы не хотите дублировать код во внешней ссылке proc, нет никакого способа избежать использования курсора.
Они говорят, что если вы должны использовать cursor, то, должно быть, вы сделали что-то неправильно ;-) вот решение без cursor:
declare @lookup_code char(8)
select distinct lookup_code
into #lookup_codes
from #workinprogress
while 1=1
begin
select @lookup_code = lookup_code from #lookup_codes
if @@rowcount = 0 break
exec proc_code_xref @lookup_code @xref_code OUTPUT
delete #lookup_codes
where lookup_code = @lookup_code
end