Почему так сложно сделать цикл в T-SQL - PullRequest
6 голосов
/ 26 февраля 2009

ОК, я знаю, что это можно сделать, я делаю это довольно часто, но почему так сложно сделать цикл в T-SQL? Я могу придумать множество причин, по которым я хочу проанализировать набор результатов запроса и сделать что-то, что просто невозможно сделать без цикла, но код для установки и выполнения моего цикла составляет> 20 строк.

Я уверен, что у других есть схожие мнения, так почему же у нас все еще нет простого способа выполнить цикл?

В сторону: мы наконец получили UPSERT (иначе MERGE) в SQL2008, так что, возможно, вся надежда не потеряна.

Ответы [ 9 ]

22 голосов
/ 26 февраля 2009

SQL является основанным на множестве, декларативным языком ; не процедурный или императивный язык . T-SQL пытается объединить эти два понятия, но он по-прежнему построен на фундаментальной парадигме множеств.

10 голосов
/ 26 февраля 2009

Я могу придумать множество причин, по которым я хотел бы проанализировать набор результатов запроса и сделать что-то, что просто невозможно сделать без цикла

И для подавляющего большинства из них я могу либо показать вам, как сделать это в операции на основе набора, либо объяснить, почему это должно быть сделано в вашем клиентском коде, а не в базе данных. Необходимость сделать цикл в SQL превышает редкость.

2 голосов
/ 26 февраля 2009

T-SQL не предназначен для использования в качестве императивного языка. Его дизайн должен быть декларативным. Его декларативный характер позволяет оптомайзеру разделять различные задачи и выполнять их параллельно, а другими способами выполнять действия в наиболее эффективном порядке.

1 голос
/ 26 февраля 2009

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

1 голос
/ 26 февраля 2009

это зависит от того, что вы хотите сделать в цикле. Использование цикла while совсем не сложно:

declare @i int
set @i = 20
while @i>0 begin
... do some stuff
set @i = @i-1
end

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

1 голос
/ 26 февраля 2009

почти все можно сделать на основе набора, попробуйте использовать таблицу чисел

почему 20 строк? Это все, что вам нужно

select *,identity(int, 1,1) as Someid into #temp
from sysobjects

declare @id int, @MaxId int
select @id = 1,@MaxId = max(Someid) from #temp

while @id < @MaxId
begin
-- do your stuff here
print @id
set @id =@id + 1
end
1 голос
/ 26 февраля 2009

Потому что SQL - это язык на основе множеств. Сила sql заключается в том, чтобы найти меньшую группу в большей группе данных на основе определенных характеристик. Чтобы справиться с этой задачей, циклы в основном не нужны. Очевидно, что он был добавлен для удобства обработки некоторых ситуаций, но предполагаемое использование языка делает эту функцию неактуальной.

0 голосов
/ 26 февраля 2009

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

WHILE - самая распространенная циклическая структура, CURSORS также можно использовать, но у них есть свои проблемы (забыв освободить / закрыть)

... пример WHILE (вам может и не понадобиться, но другим это может понадобиться)

DECLARE @iterator INT
SET @iterator = 0

WHILE @iterator < 20
BEGIN
  SELECT * FROM table WHERE rowKey = @iterator
/*do stuff*/
  @iterator = @iterator + 1
END

Реальный вопрос в том, «Что вы пытаетесь сделать, что просто невозможно сделать способом, основанным на множестве?»

0 голосов
/ 26 февраля 2009

Я не специалист по БД, но я считаю, что атомарная природа транзакций базы данных затруднит выполнение циклов, потому что транзакция завершена или ее вообще не должно происходить. Поддержание состояния может быть противным!

Статья в Википедии об атомарности

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...