С помощью курсора или цикла while или любым другим способом?

#sql-server-2008 #stored-procedures #cursor #while-loop #recordset

#sql-server-2008 #хранимые процедуры #курсор #цикл while #набор записей

Вопрос:

Я прошел через несколько обсуждений, связанных (не точных) с этим, но я хочу знать правильное решение моей ситуации, поэтому публикую этот вопрос.

Мне нужно выбрать некоторые записи из таблицы на основе некоторого условия и передать значения каждой записи в SP.

Я подумал об использовании курсора для перебора набора записей, после некоторого поиска в Google я обнаружил, что цикл while также используется, и есть много обсуждений, какой из них лучше, и большинство из них сказали, что это зависит от ситуации. Теперь я не могу судить о своей ситуации, следовательно, обращаясь к экспертам.

Вот цикл while, о котором я подумал:

 Table Test
{
  id int
  value int
  -- Some more fields
}

WHILE EXISTS(SELECT TOP 1 id FROM Test WHERE isValid=1)
BEGIN
  DECLARE @id AS INT
  DECLARE @value AS INT
  SELECT TOP 1 @id=id, @value=value FROM Test WHERE isValid=1
  EXEC SP_SomeProcessingSP @id, @value -- Some more fields passed to it from above table
  -- After execution of the above SP I need to update the record to invalid
  UPDATE Test SET isValid = 0 WHERE id=@id
END
  

Этот подход лучше, чем cursor? Было бы здорово, если бы кто-нибудь мог придумать лучшее решение без while и cursor (я хочу избежать обоих).

Редактировать: Изменен блок while, а также приведен пример таблицы. Теперь SP, который вызывается внутри этого блока while, обращается к данным из пары таблиц и выполняет некоторую обработку и вставляет данные в пару других таблиц.

Комментарии:

1. Возможно, вы захотите рассмотреть возможность использования хранимой процедуры CLR . Я не уверен в его плюсах и минусах. Может быть, кто-то более осведомленный в этом может пролить больше света.

Ответ №1:

Похоже, что это обходной путь:

 UPDATE Test SET isValid = 0 WHERE isValid = 1
  

Что касается того, какой подход является лучшим, вы не предоставили достаточно подробностей для ответа.

Это полностью зависит от того, что вы пытаетесь сделать. Возможно, рекурсивный CTE решит ваши проблемы без необходимости вызывать хранимую процедуру. Возможно, хорошее объединение решило бы эту проблему. Возможно, лучшим было бы другое решение.

Вам нужно объяснить, чего именно вы пытаетесь достичь.

Комментарии:

1. Упс, вы неправильно поняли мой вопрос. Вы пропустили мой блок комментариев между статментом выбора и обновления. Я буду вызывать другой SP со значениями, полученными из инструкции select .

2. @JPReddy — Нет, я этого не делал. Просто недостаточно информации.

3. Я обновил свой вопрос, чтобы предоставить дополнительную информацию. Я надеюсь, что этой информации достаточно, пожалуйста, дайте мне знать, если вам нужно больше.

4. @JPReddy — Это зависит от того, что делает SP. Возможно, что вы можете просто передать весь список идентификаторов хранимой процедуре за один раз. В общем, лучше использовать операции набора (объединения и т.д.) Вместо циклов любого вида.

5. Понял вашу точку зрения, не могу сделать такую вещь. Потому что это существующий SP, и я должен его использовать. Похоже, я должен использовать While или Cursor

Ответ №2:

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

Проверьте параметры, оцениваемые в таблице, здесь: http://msdn.microsoft.com/en-us/library/bb510489.aspx