如何在 PL/SQL 中使用循环多次运行相同的查询?

Posted

技术标签:

【中文标题】如何在 PL/SQL 中使用循环多次运行相同的查询?【英文标题】:How can you run the same query multiple times using loop in PL/SQL? 【发布时间】:2016-01-14 12:00:20 【问题描述】:

使用此代码我无法多次运行插入查询;它只询问一次 ID 和名称(如果计数器中的值大于 1)。

declare
        counter number := 0 ;
begin 
        counter := &counter ;
        while counter > 0 loop
               insert into customer values ( &id, '&name' ) ;
               counter := counter - 1 ;
       end loop ;
end ;   

让我用一个例子来解释一下:-

假设我将值 2 放入 counter。有了这个,它应该两次询问我的 ID 和名称,但它只询问一次,并将我为 ID 和名称输入的值复制到表 test 中两次。

我该如何解决这个问题?如果我不能,请建议可以解决我的问题的替代代码。

【问题讨论】:

你能展示你声明中的所有代码吗? 您可能需要查看此信息以了解获取用户输入的替代方法:safaribooksonline.com/library/view/oracle-sqlplus-the/…。另外,我猜你正在使用 SQL/Plus。您应该相应地标记您的问题。 【参考方案1】:

当编译 PL/SQL 块时,替换变量 &counter&id&name 分别被计算一次 - 不是,因为它正在执行。

变量不会,也不能在 PL/SQL 块内重新评估或重新提升。该块在数据库中作为一个单元执行——一旦它被提交执行,它就独立于客户端,它只是等待它完成(除非你中断它,客户端也处理它)。 PL/SQL 不是一种交互式语言,您不应将客户端功能(例如替换变量)与 SQL 或 PL/SQL 功能混淆。


只是为了好玩,您可以基于counter 生成一个脚本,该脚本对 ID 和名称进行适当数量的提示,并将它们转换为可以通过简单插入使用的格式:

set serveroutput on
set feedback off
set echo off
set verify off
set termout off

accept counter "How many value pairs do you want to insert?"

var ids varchar2(4000);
var names varchar2(4000);

spool /tmp/prompter.sql

begin
  -- prompt for all the value pairs
  for i in 1..&counter loop
    dbms_output.put_line('accept id' ||i|| ' number  "Enter ID ' ||i|| '"');
    dbms_output.put_line('accept name' ||i|| '  char "Enter name ' ||i|| '"');
  end loop;

  -- concatenate the IDs into one variable
  dbms_output.put('define ids="');
  for i in 1..&counter loop
    if i > 1 then
      dbms_output.put(',');
    end if;
    dbms_output.put('&'||'id'||i);
  end loop;
  dbms_output.put_line('"');

  -- concatenate the names into one variable
  dbms_output.put('define names="');
  for i in 1..&counter loop
    if i > 1 then
      dbms_output.put(',');
    end if;
    -- each name wrapped in single quotes
    dbms_output.put(q'['&]'||'name'||i||q'[']');
  end loop;
  dbms_output.put_line('"');
end;
/
spool off

@/tmp/prompter

insert into customer (id, name)
select i.id, n.name
from (
  select rownum as rid, column_value as id 
  from table(sys.odcinumberlist(&ids))
) i
join (
  select rownum as rid, column_value as name
  from table(sys.odcivarchar2list(&names))
) n
on n.rid = i.rid;

select * from customer;

这会创建一个名为 prompter.sql 的文件(我已将其放在 /tmp 中;将其放在适合您环境的地方!); '值对的数量'提示回答为 2,临时脚本看起来包含:

accept id1 number  "Enter ID 1"
accept name1  char "Enter name 1"
accept id2 number  "Enter ID 2"
accept name2  char "Enter name 2"
define ids="&id1,&id2"
define names="'&name1','&name2'"

然后使用@ 运行该临时脚本,提示用户输入所有这些单独的值。然后在 select 中使用由组合替换变量构建的 table 集合,该 select 由 insert 使用。

【讨论】:

那么就没有办法了吗?? @AhtishamChishti - 不是一个简单的方法。这是一个练习还是您真正需要使用交互式提示做的事情?

以上是关于如何在 PL/SQL 中使用循环多次运行相同的查询?的主要内容,如果未能解决你的问题,请参考以下文章

如何从选择查询向 PL/SQL 循环提供值

PL/SQL 迭代所有模式并在所有模式上运行相同的查询

在打算多次运行的 Oracle PL/SQL 脚本中,是不是需要清除集合?

如何使用PL / SQL更改您在FOR循环IN子句中查询的表

如何使用 pl/sql 为多行填充相同的值

在 PL/SQL Developer 中运行的日期查询显示时间,但在 Oracle SQL Developer 中不显示