SQL游标怎么循环更新

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL游标怎么循环更新相关的知识,希望对你有一定的参考价值。

怎么使用SQL游标更新临时表中'aa'字段下大于100条记录的数据

select a.OID,0 as ewaibutie into #aa from Man_FinishRecord a
当游标查询到的记录数大于100的时候#aa表中的ewaibutie 字段每一条都更新成5

求大神贴代码!
declare @ewaibutie int
declare @i int
set @i=0
declare cur_man cursor scroll dynamic
for
select ewaibutie from #aa
OPEN cur_man
FETCH NEXT from cur_man into @ewaibutie
WHILE @@FETCH_STATUS = 0
BEGIN
if(@i > 100)
begin
update #aa set @ewaibutie = 5
set @i = @i + 1
end
FETCH NEXT from cur_man into @ewaibutie
END
CLOSE cur_man
DEALLOCATE cur_man

结果没有任何变化,求解释

参考技术A 应该不是游标问题,是循环内的判定问题,@i一直没变过,所以 @i>100不会命中。将set @i提出来:
WHILE @@FETCH_STATUS = 0
BEGIN
set @i = @i + 1
if(@i > 100)
begin
update #aa set @ewaibutie = 5
end
FETCH NEXT from cur_man into @ewaibutie
END
CLOSE cur_man追问

5 还是没有更新到临时表中去啊

参考技术B 应该不是游标问题,是循环内的判定问题,@i一直没变过,所以 @i>100不会命中。将set @i提出来:
WHILE @@FETCH_STATUS = 0
BEGIN
set @i = @i + 1
if(@i > 100)
begin
update #aa set @ewaibutie = 5
end
FETCH NEXT from cur_man into @ewaibutie
END
CLOSE cur_man

循环遍历带有更新字段条件的游标 [PLSQL]

【中文标题】循环遍历带有更新字段条件的游标 [PLSQL]【英文标题】:Looping through a cursor with a condition on an updated field [PLSQL] 【发布时间】:2017-09-18 18:10:53 【问题描述】:

我目前正在实现一个 PL/SQL 过程,它可以平衡两个列表中的值。

将此示例视为背景:

Rec_1 | 2 Rec_2 | 1 Rec_3 | 2
Rec_A | -1 Rec_B | -3 Rec_C | -2

我想逐个循环遍历所有这些值并尽可能多地结算,即第一次结算后 Rec_1 应该是 1,Rec_A 应该是 0。之后,Rec_1 将与 Rec_B 结算,这样它得到 1,Rec_B 得到 -2,以此类推。

我想使用两个游标来执行此操作,并在它自己的过程(或函数,如果有必要的话)中更新值,因为除了更新这个值之外,还有更多工作要做。

现在,这是我的挑战: 在结算发生后,我如何知道要获取哪个光标?

现在,我的这个函数的代码如下所示:

PROCEDURE SettleLists (
  ListNegV SYS_REFCURSOR,
  ListPosV SYS_REFCURSOR
) IS
  currentNegV TABLENAME%ROWTYPE;
  currentPosV TABLENAME%ROWTYPE;
BEGIN
  FETCH ListNegV INTO currentNegV;
  FETCH ListPosV INTO currentPosV;
  LOOP
    EXIT WHEN ListNegV%NOTFOUND;
    EXIT WHEN ListPosV%NOTFOUND;
    IF (currentNegV.NUMERICVALUE < 0)
    THEN
      IF (currentPosV.NUMERICVALUE > 0)
      THEN
        Settle(currentPosV, currentNegV);
      ELSE 
        FETCH ListPosV INTO currentPosV;
      END IF;
    ELSE 
      FETCH ListNegV INTO currentNegV;
    END IF;  
  END LOOP;
END;

在结算过程中,两条记录都会有更新。由于变量和游标值没有更新,这将产生一个无限循环。我也可以在数据库中更新记录时更新结算参数,但由于我不习惯游标,您可能会有更好的主意。

我可以认为光标是强类型的,如果这有什么不同的话。如果有比使用光标更好的方法,请随时提出建议。

最后,我在玩 SELECT FOR UPDATE 和 UPDATE WHERE CURRENT OF,但在将游标传递给介于两者之间的过程时,它似乎不起作用。如果有人对此有一些想法,我也将感谢您的帮助。

【问题讨论】:

【参考方案1】:

这是我要做的。我一定会添加一些cmets。

这在 Oracle 11Gr2 中运行良好,我希望即使在 7i 中也能正常运行 :)。

declare
    cursor c1 is 
        select 'REC_1' HEader,2 Val from dual
        union 
        select 'REC_2' HEader,1 Val from dual
        union 
        select 'REC_3' HEader,2 Val from dual;
    cursor c2 is
        select 'REC_A' HEader,-1 Val from dual
        union 
        select 'REC_B' HEader,-3 Val from dual
        union 
        select 'REC_C' HEader,-2 Val from dual;
    num_bal1 number;
    num_bal2 number;
    num_settle_amt number;
    rec_type_c1 c1%rowtype;
    rec_type_c2 c2%rowtype;
begin

    Open c1;
    open c2;
    fetch c1 into rec_type_c1;
    fetch c2 into rec_type_c2;
    num_bal1 := nvl(rec_type_c1.val,0);
    num_bal2 := rec_type_c2.val;
    Loop

        exit when c1%notfound or c2%notfound;
        Loop
            dbms_output.put_line('Processing ' || rec_type_c1.header || ' with ' || num_bal1);
            --In your example there are only +ve for 1 and -ve for 2. But if that is not correct, check for signs and next 3 statements
            num_settle_amt := least(abs(num_bal1), abs(num_bal2) );
            num_bal1 := num_bal1 - num_settle_amt;
            num_bal2 := num_bal2 + num_settle_amt;
            dbms_output.put_line('Setteled ' || num_settle_amt || ' of ' || rec_type_c1.header  || ' with ' || rec_type_c2.header );
            if num_bal1 = 0 then
                --Update in the table. It will not impact variable.
                fetch c1 into rec_type_c1;
                num_bal1 := nvl(rec_type_c1.val,0);
            end if;

            if num_bal2 = 0 then
                --Update in the table. It will not impact variable.
                fetch c2 into rec_type_c2;
                num_bal2 := nvl(rec_type_c2.val,0);
            end if;

        End loop;
    end loop;
    close c1;
    close c2;
end;

【讨论】:

感谢您花时间编写此代码。这很好用,我只是认为会有一些技术可以在不更新表和变量的情况下实现这一点。

以上是关于SQL游标怎么循环更新的主要内容,如果未能解决你的问题,请参考以下文章

SQL游标怎么用

pl / sql如何使用带有游标的for循环进行更新操作

sqlserver中游标循环中只更新当前行的方法

求一条sql循环语句

SQL中游标的使用--遍历数据逐行更新或删除:相当于for循环

sqlserver中怎样使用游标for循环