我可以在T-SQL中循环表变量吗?

Kuy*_*nda 66 sql t-sql sql-server cursor table-variable

反正是否在T-SQL中循环表变量?

DECLARE @table1 TABLE ( col1 int )  
INSERT into @table1 SELECT col1 FROM table2
Run Code Online (Sandbox Code Playgroud)

我也使用游标,但游标似乎不如表变量灵活.

DECLARE cursor1 CURSOR  
    FOR SELECT col1 FROM table2  
OPEN cursor1  
FETCH NEXT FROM cursor1
Run Code Online (Sandbox Code Playgroud)

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

任何帮助是极大的赞赏.

KM.*_*KM. 95

为表变量添加一个标识,并从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
Run Code Online (Sandbox Code Playgroud)

  • 这似乎是最简单的.谢谢! (4认同)

Jus*_*ner 14

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
Run Code Online (Sandbox Code Playgroud)

信不信由你,这实际上比使用光标更有效率和更高效.


typ*_*rpr 8

我的两分钱..来自KM.答案,如果你想删除一个变量,你可以对@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
Run Code Online (Sandbox Code Playgroud)


Raj*_*ore 6

您可以遍历表变量,也可以光标浏览它.这就是我们通常所说的RBAR - 发音为Reebar,意味着Row-By-Agonizing-Row.

我建议找一个基于SET的答案来解答你的问题(我们可以帮助你),并尽可能地远离rbars.


Gil*_*dor 5

看起来像这个演示:

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
Run Code Online (Sandbox Code Playgroud)

没有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
Run Code Online (Sandbox Code Playgroud)