1) Это твердо
2), Это занимает время
3), очень трудно решить, что значение тестового кода
Точка 3 является липким. Хорошие модульные тесты уменьшают ошибки. Но хороший производственный код - также. Как Вы определяете, сколько ошибок не существует из-за Ваших модульных тестов? Вы не можете измерить то, что не существует. Можно указать на исследования, но они не соответствуют приятно на электронной таблице управляющего делами.
Добавить идентификатор вашей переменной таблицы и выполните простой цикл от 1 до @@ ROWCOUNT в INSERT-SELECT.
Попробуйте следующее:
DECLARE @RowsToProcess int
DECLARE @CurrentRow int
DECLARE @SelectCol1 int
DECLARE @table1 TABLE (RowID int not null primary key identity(1,1), col1 int )
INSERT into @table1 (col1) SELECT col1 FROM table2
SET @RowsToProcess=@@ROWCOUNT
SET @CurrentRow=0
WHILE @CurrentRow<@RowsToProcess
BEGIN
SET @CurrentRow=@CurrentRow+1
SELECT
@SelectCol1=col1
FROM @table1
WHERE RowID=@CurrentRow
--do your thing here--
END
DECLARE @table1 TABLE (
idx int identity(1,1),
col1 int )
DECLARE @counter int
SET @counter = 1
WHILE(@counter < SELECT MAX(idx) FROM @table1)
BEGIN
DECLARE @colVar INT
SELECT @colVar = col1 FROM @table1 WHERE idx = @counter
-- Do your work here
SET @counter = @counter + 1
END
Хотите верьте, хотите нет, но на самом деле это более эффективно и производительно, чем использование курсора.
Вы можете перемещаться по табличной переменной или перемещаться по ней курсором. Это то, что мы обычно называем RBAR - произносится как Reebar и означает Row-By-Agonizing-Row.
Я бы посоветовал найти НАБОРНЫЙ ответ на ваш вопрос (мы можем помочь с этим) и максимально отказаться от rbars насколько возможно.
Вот мой вариант. Практически так же, как и все остальные, но я использую только одну переменную для управления циклом.
DECLARE
@LoopId int
,@MyData varchar(100)
DECLARE @CheckThese TABLE
(
LoopId int not null identity(1,1)
,MyData varchar(100) not null
)
INSERT @CheckThese (MyData)
select MyData from MyTable
order by DoesItMatter
SET @LoopId = @@rowcount
WHILE @LoopId > 0
BEGIN
SELECT @MyData = MyData
from @CheckThese
where LoopId = @LoopId
-- Do whatever
SET @LoopId = @LoopId - 1
END
Точка зрения Раджа Мора актуальна - выполняйте циклы только в том случае, если это необходимо.
Я не знал о структуре WHILE.
Структура WHILE с табличной переменной, однако, похожа на использование КУРСОРА, поскольку вам все равно нужно ВЫБРАТЬ строку в переменная, основанная на строке IDENTITY, которая фактически является FETCH.
Есть ли разница между использованием WHERE и чем-то вроде следующего?
DECLARE @table1 TABLE ( col1 int )
INSERT into @table1 SELECT col1 FROM table2
DECLARE cursor1 CURSOR
FOR @table1
OPEN cursor1
FETCH NEXT FROM cursor1
Я не знаю, возможно ли это вообще. Полагаю, вам придется сделать следующее:
DECLARE cursor1 CURSOR
FOR SELECT col1 FROM @table1
OPEN cursor1
FETCH NEXT FROM cursor1
Спасибо за помощь!
Вот еще один ответ, похожий на ответ Джастина, но не требующий идентификационных данных или совокупности, только первичный (уникальный) ключ.
declare @table1 table(dataKey int, dataCol1 varchar(20), dataCol2 datetime)
declare @dataKey int
while exists select 'x' from @table1
begin
select top 1 @dataKey = dataKey
from @table1
order by /*whatever you want:*/ dataCol2 desc
-- do processing
delete from @table1 where dataKey = @dataKey
end