2010-04-05 2 views
1

Это не трудно найти разработчиков who think cursors are gauche, но мне интересно, как решить следующую проблему без одного:Запуск хранимой процедуры с параметрами, в результате запроса

Допустим, я прок называется uspStudentDelete, который принимает в качестве параметра @Студенческий билет.

uspStudentDelete применяет кучу каскадной логики мягкого удаления, отмечая флаг в таблицах типа «классы», «оценки» и т. Д. Как неактивные. uspStudentDelete хорошо проверен и работал некоторое время.

Что бы лучший способ запустить uspStudentDelete по результатам запроса (например, выберите studentid из студентов где ...) вTSQL?

+3

Курсоры не являются gauche, они являются производителями убийц. Их следует избегать в любое время, когда набор данных будет работать. Это может быть разница между процессом, принимающим часы или дни или миллисекунды или минуты. – HLGEM

+0

От этого явно зависит. Для больших томов следует использовать процедуру удаления, чтобы иметь возможность обрабатывать несколько учеников и выполнять все зависимые удаления в режиме набора (решение HLGEM). Для небольших томов вызов одноуровневого удаления не будет выполняться плохо и избавит вас от необходимости перезаписывать SP (решение Andomar). –

+0

** вы можете зацикливаться без курсора. ** Мне пришлось ускорить медленные петли курсора, где была сумасшедшая логика IF, и вызывает многие другие процедуры в цикле. В некоторых случаях было невозможно удалить петлю. Однако я удалил курсор (оставил цикл) и все еще имел значительные улучшения производительности. просто google "sql server cursor free loop" –

ответ

3

Это именно то, что курсоры предназначены для:

declare c cursor local for <your query here> 
declare @ID int 
open c 
fetch next from c into @id 
while @@fetch_status = 0 
    begin 
    exec uspStudentDelete @id 
    fetch next from c into @id 
    end 
close c 
deallocate c 

Большинство людей, которые ругают курсоров думают, что вы должны сделать это в надлежащем клиенте, как C# настольных приложений.

+2

Это именно то, чего вы не должны делать. Это убьет производительность. – HLGEM

+1

@HLGem: OP говорит, что его текущий proc «хорошо проверен», поэтому я думаю, что повторное использование хорошо проверенного кода более важно, чем производительность. И, надеюсь, он не удаляет 10 000 студентов каждый день :) – Andomar

+0

@HLGem: @Andomar верна в обоих случаях - во-первых, эта процедура существовала для многих наших циклов разработки как важная часть процесса и что мы говорим о горстке не более чем на 50+. Моя дилемма с тем, что вы говорите, заключается в том, что вы говорите о копировании/вставке существующей логики на основе SET, чтобы существовать в двух местах, что создало бы еще одну проблему: ремонтопригодность. – t3rse

3

Лучшее решение - написать обработчик на основе набора для обработки удаления (попробуйте запустить его с помощью курсора, чтобы удалить 10 000 записей, и вы увидите, почему) или добавить код на основе текущего процесса с помощью параметр, указывающий на то, что вы запускаете единицу или единую запись в proc (это, по крайней мере, удерживает ее вместе для целей обслуживания).

В SQL Server 2008 вы можете использовать переменную таблицы в качестве входной переменной. Если вы переписываете proc на основе набора, вы можете иметь такую ​​же логику и запускать ее независимо от того, отправляет ли proc одну запись или десять тысяч. Возможно, вам понадобится пакетный процесс, чтобы избежать удаления миллионов записей за один раз и блокировать таблицы в течение нескольких часов. Конечно, если вы это сделаете, вам также нужно будет настроить способ вызова currect sp.

+1

+1 аминь, брат! Небольшой набор рефакторинга может помочь легко избежать курсоров здесь –

Смежные вопросы