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

时间:2016-01-14 12:00:20

标签: sql oracle plsql

使用此代码我无法多次运行插入查询;它只询问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两次。

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

1 个答案:

答案 0 :(得分:5)

当编译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中;把它放在适合你环境的地方!);将“值对数”提示符回答为临时脚本看起来包含的内容:

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'"

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