如何获取 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
您可以在没有游标的情况下使用 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
我正在使用 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
您可以在没有游标的情况下使用 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