首页 > 解决方案 > 关于 Oracle PL SQL 循环

问题描述

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

点击查看代码

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

点击查看代码

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

为什么要这样解释?

标签: oracleloopsplsqldatabase-sequence

解决方案


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

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为 true)。由于单行结果集已用尽,第二次和后续提取未找到行。

简而言之,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

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


推荐阅读