我可以在T-SQL中循环一个表variables吗?

无论如何循环T-SQL中的表variables?

DECLARE @table1 TABLE ( col1 int ) INSERT into @table1 SELECT col1 FROM table2 

我也使用游标,但是游标似乎不如表variables灵活。

 DECLARE cursor1 CURSOR FOR SELECT col1 FROM table2 OPEN cursor1 FETCH NEXT FROM cursor1 

我希望能够以与游标相同的方式使用表variables。 这样,我可以在过程的一部分中对表variables执行一些查询,然后稍后为表variables中的每一行执行一些代码。

任何帮助是极大的赞赏。

为表variables添加一个标识,并从1到INSERT-SELECT的@@ ROWCOUNT进行一个简单的循环。

尝试这个:

 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 

相信与否,这实际上比使用游标更高效,更高效。

你可以遍历表variables,或者你可以通过它的光标。 这就是我们通常所说的RBAR(发音为Reebar),意思是逐行排列。

我会build议find一个基于问题的答案(我们可以帮助解决这个问题),并尽可能远离rbars。

看起来像这个演示:

 DECLARE @vTable TABLE (IdRow int not null primary key identity(1,1),ValueRow int); -------Initialize--------- insert into @vTable select 345; insert into @vTable select 795; insert into @vTable select 565; --------------------------- DECLARE @cnt int = 1; DECLARE @max int = (SELECT MAX(IdRow) FROM @vTable); WHILE @cnt <= @max BEGIN DECLARE @tempValueRow int = (Select ValueRow FROM @vTable WHERE IdRow = @cnt); ---work demo---- print '@tempValueRow:' + convert(varchar(10),@tempValueRow); print '@cnt:' + convert(varchar(10),@cnt); print''; -------------- set @cnt = @cnt+1; END 

没有idRow的版本,使用ROW_NUMBER

  DECLARE @vTable TABLE (ValueRow int); -------Initialize--------- insert into @vTable select 345; insert into @vTable select 795; insert into @vTable select 565; --------------------------- DECLARE @cnt int = 1; DECLARE @max int = (select count(*) from @vTable); WHILE @cnt <= @max BEGIN DECLARE @tempValueRow int = ( select ValueRow from (select ValueRow , ROW_NUMBER() OVER(ORDER BY (select 1)) as RowId from @vTable ) T1 where t1.RowId = @cnt ); ---work demo---- print '@tempValueRow:' + convert(varchar(10),@tempValueRow); print '@cnt:' + convert(varchar(10),@cnt); print''; -------------- set @cnt = @cnt+1; END 

我的两分钱..从KM。的答案,如果你想删除一个variables,你可以在@RowsToProcess上进行倒计时,而不是计数。

 DECLARE @RowsToProcess 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 WHILE @RowsToProcess > 0 -- Countdown BEGIN SELECT * FROM @table1 WHERE RowID=@RowsToProcess --do your thing here-- SET @RowsToProcess = @RowsToProcess - 1; -- Countdown END 

这里有另一个答案,类似于贾斯汀的,但不需要身份或聚合,只是一个主要(唯一)的关键。

 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 

这是我的变种。 几乎和所有其他的一样,但我只使用一个variables来pipe理循环。

 DECLARE @LoopId int ,@MyData varchar(100) DECLARE @CheckThese TABLE ( LoopId int not null identity(1,1) ,MyData varchar(100) not null ) INSERT @CheckThese (YourData) 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 

Raj More的观点是相关的 – 只有在必要时才执行循环。

我不知道WHILE结构。

然而,使用表variables的WHILE结构看起来类似于使用CURSOR,因为您仍然必须根据行IDENTITY将行select到variables中,该行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 

感谢您的帮助!

这是我的版本相同的解决scheme…

  declare @id int SELECT @id = min(fPat.PatientID) FROM tbPatients fPat WHERE (fPat.InsNotes is not null AND DataLength(fPat.InsNotes)>0) while @id is not null begin SELECT fPat.PatientID, fPat.InsNotes FROM tbPatients fPat WHERE (fPat.InsNotes is not null AND DataLength(fPat.InsNotes)>0) AND fPat.PatientID=@id SELECT @id = min(fPat.PatientID) FROM tbPatients fPat WHERE (fPat.InsNotes is not null AND DataLength(fPat.InsNotes)>0)AND fPat.PatientID>@id end