如何获取 SQL 中 Cursor 结果集中行的最新值

How to get Latest value of row in Cursor result set in SQL

我正在使用 Cursor 对我在 Cursor 的 Select 语句中使用的相同 table 进行一些操作,如下所示,

CREATE TABLE #nsn (ID INT IDENTITY(1,1)
,Val1 Varchar(MAx)
,Val2 Varchar(MAx)
)

INSERT INTO #nsn(Val1,VAl2) select 'A1','A2'
INSERT INTO #nsn(Val1,VAl2) select 'B1','B2'
INSERT INTO #nsn(Val1,VAl2) select 'C1','C2'
INSERT INTO #nsn(Val1,VAl2) select 'D1','D2'
INSERT INTO #nsn(Val1,VAl2) select 'E1','F2'

SELECT * From #nsn
ID  Val1    VAl2
1|  A1  |   A2
2|  B1  |   B2
3|  C1  |   C2
4|  D1  |   D2
5|  E1  |   F2

使用游标更新 Val2 列,

DECLARE @ID INT 
        ,@Val1 Varchar(MAx)
        ,@Val2 Varchar(MAx)

DECLARE cursor_Latest CURSOR
FOR SELECT  ID,Val1,Val2
    FROM    #nsn 
    ORder by 1 asc
OPEN cursor_Latest
FETCH NEXT FROM cursor_Latest INTO  @ID , @Val1 ,@Val2
WHILE (@@FETCH_STATUS <> -1)
BEGIN
    UPDATE #nsn
    SET Val2 = Val2 +'-'+ @Val1 +'-'+@Val2
    WHERE ID = @ID+1

    FETCH NEXT FROM cursor_Latest INTO  @ID , @Val1 ,@Val2
END
close cursor_Latest
DEALLOCATE cursor_Latest

其结果是

SELECT * From #nsn
ID  Val1    VAl2
1|  A1  |   A2
2|  B1  |   B2-A1-A2
3|  C1  |   C2-B1-B2
4|  D1  |   D2-C1-C2
5|  E1  |   F2-D1-D2

但我期待如下结果,

ID  Val1    VAl2
1|  A1  |   A2
2|  B1  |   B2-A1-A2
3|  C1  |   C2-B1-B2-A1-A2
4|  D1  |   D2-C1-C2-B1-B2-A1-A2
5|  E1  |   F2-D1-D2-C1-C2-B1-B2-A1-A2

那么这段代码有什么问题吗?要么 Cursor 是否有任何记录存储的东西,因为它没有获取新行的最新更新值。

预先感谢您的帮助..

尝试在游标声明中指定 "DYNAMIC" 选项。

DECLARE cursor_Latest CURSOR DYNAMIC

网上的书是这么说的:
"Defines a cursor that reflects all data changes made to the rows in its result set as you scroll around the cursor. The data values, order, and membership of the rows can change on each fetch."

换句话说,每次提取都会再次提取数据,它会反映刚刚所做的更改。因此 VAL2 将获得您想要的正确连接。

要达到您的预期结果,您应该尝试以下操作,

DECLARE @ID       INT
       ,@Val1     VARCHAR(MAX)
       ,@Val2     VARCHAR(MAX)

DECLARE cursor_Latest CURSOR  
FOR
    SELECT ID,Val1,Val2 FROM   #nsn
    ORDER BY 1 ASC

OPEN cursor_Latest
FETCH NEXT FROM cursor_Latest INTO  @ID , @Val1 ,@Val2
WHILE (@@FETCH_STATUS<>-1)
BEGIN
    IF @ID=1
    BEGIN
        UPDATE #nsn
        SET    Val2     = Val2+'-'+@Val1+'-'+@Val2
        WHERE  ID       = @ID+1
    END
    ELSE
    BEGIN
        UPDATE #nsn
        SET    Val2   = Val2+'-'+@Val1+'-'+@Val2+'-'+( SELECT Val1+'-'+Val2 FROM   #nsn WHERE  ID     = @ID-1)
        WHERE  ID                = @ID+1
    END 

    FETCH NEXT FROM cursor_Latest INTO @ID , @Val1 ,@Val2
END
CLOSE cursor_Latest
DEALLOCATE cursor_Latest

SELECT * FROM   #nsn
DROP TABLE  #nsn

SQL Fiddle Demo

您可以在没有游标的情况下使用 for xml 连接相关子查询中的值来执行此操作。

update N1
set Val2 = (
           select case when N1.ID = N2.ID then '' else '-' + N2.Val1 end + '-' + N2.Val2
           from #nsn as N2
           where N1.ID >= N2.ID
           order by N2.ID desc
           for xml path(''), type
           ).value('substring(text()[1], 2)', 'varchar(max)')
from #nsn as N1

这会进行三角自连接,因此如果您有很多行,游标版本可能是更快的选择。尝试找出答案。

CREATE TABLE #nsn (ID INT IDENTITY(1,1),Val1 Varchar(MAx),Val2 Varchar(MAx)) 

INSERT INTO #nsn(Val1,VAl2) select 'A1','A2'
INSERT INTO #nsn(Val1,VAl2) select 'B1','B2'
INSERT INTO #nsn(Val1,VAl2) select 'C1','C2'
INSERT INTO #nsn(Val1,VAl2) select 'D1','D2'
INSERT INTO #nsn(Val1,VAl2) select 'E1','F2'

DECLARE  @ID INT 
        ,@Val1 Varchar(MAx)
        ,@Val2 Varchar(MAx)
        ,@v1 Varchar(MAx)
        ,@v2 Varchar(MAx)
        ,@t Varchar(MAx),@val varchar(max)
        set @ID=1 


while @ID<=(select count(*) from #nsn)
begin
select @v1=val1,@v2=val2 from #nsn where ID=@ID
select @Val1=val1,@Val2=val2 from #nsn where id=@ID+1
update #nsn set val2= case when @val is not null then  @Val2+'-'+@v1+'-'+@val else @Val2+'-'+@v1+'-'+@v2  end  where id=@ID+1
select  @val=@Val2+'-'+@v1+'-'+@v2
set @ID=@ID+1
end
SELECT * From #nsn

声明 @ID INT ,@Val1 Varchar(MAX),@Val2 Varchar(MAx) ,@v1 Varchar(MAx) ,@v2 变量(最大值),@t 变量(最大值),@val 变量(最大值) 设置@ID=1
while @ID<=(select count(*) 来自#nsn)
开始
select @v1=val1,@v2=val2 来自 #nsn 其中 ID=@ID
select @Val1=val1,@Val2=val2 来自 #nsn where id=@ID+1
更新#nsn set val2= case when @val is not null then @Val2+'-'+@v1+'-'+@val else @Val2+'-'+@v1+'-'+@v2 end where id=@ID+1
select @val=@Val2+'-'+@v1+'-'+@v2
设置@ID=@ID+1
结束
SELECT * 来自#nsn