关于 Oracle PL SQL 循环

Posted

技术标签:

【中文标题】关于 Oracle PL SQL 循环【英文标题】:regarding Oracle PL SQL Loop 【发布时间】:2018-10-24 14:43:05 【问题描述】:

今天做一些编码。遇到以下序列问题。 PL/SQL 中的这段代码:

没有按预期工作,即序列没有按我的意愿增加 10 - 仅增加 1。这段代码:

工作正常。序列按预期递增 10。

为什么要这样解释?

【问题讨论】:

Please post formatted text, not images. 我认为您不需要输入此代码并查看..我希望在这里得到概念性答案..因为在这些图像中我也没有提供完整代码..我只需要知道为什么这种事情发生 你为什么用图片替换你的代码? 【参考方案1】:

您可以通过添加一些调试来查看发生了什么:

create sequence s42;

set serveroutput on

declare
  cursor c is
    select s42.nextval from dual;
  n pls_integer;
begin
  open c;
  for i in 1..5 loop
    fetch c into n;
    dbms_output.put_line('i: ' || i
      || '; n: ' || n
      || '; found: ' || case when c%found then 'true' else 'false' end);
  end loop;
  close c;
end;
/

i: 1; n: 1; found: true
i: 2; n: 1; found: false
i: 3; n: 1; found: false
i: 4; n: 1; found: false
i: 5; n: 1; found: false


PL/SQL procedure successfully completed.

您只打开一次游标,游标只返回一行。因此,第一次 fetch 找到了一个值(c%found 为真)。由于单行结果集已经用完,第二次和后续的提取没有找到行。

简而言之,nextval 只执行一次,所以序列只递增一次。

在您的第二个版本中,整个查询在循环内重新执行,因此nextval 被多次调用,因此序列也被多次递增。

如果你在循环内重新打开光标,你会看到同样的结果:

declare
  cursor c is
    select s42.nextval from dual;
  n pls_integer;
begin
  for i in 1..5 loop
    open c;
    fetch c into n;
    dbms_output.put_line('i: ' || i
      || '; n: ' || n
      || '; found: ' || case when c%found then 'true' else 'false' end);
    close c;
  end loop;  
end;
/

i: 1; n: 2; found: true
i: 2; n: 3; found: true
i: 3; n: 4; found: true
i: 4; n: 5; found: true
i: 5; n: 6; found: true

但这实际上只是一种更长、更复杂的 select ... into 方法,因为它一次只能返回一行。

【讨论】:

【参考方案2】:

仅在第二个代码中执行 nextval 10 次,因为 NEXTVAL 在循环内调用

NEXTVAL 导致增量

NEXTVAL:递增序列并返回下一个值

第一个代码调用nextval一次并将值存储在游标中,然后相同的值在循环中更新10次

【讨论】:

以上是关于关于 Oracle PL SQL 循环的主要内容,如果未能解决你的问题,请参考以下文章

Oracle PL/SQL之LOOP循环控制语句

oracle pl/sql 控制结构(分支,循环,控制)

循环遍历 Oracle PL/SQL 中的表

循环字符串时如何插入临时表 - Oracle - PL/SQL

在 Oracle PL/SQL 中复制 SAS DO 循环

Oracle PL/SQL之LOOP循环控制语句