Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

oracle - How can you run the same query multiple times using loop in PL/SQL?

Using this code I'm not able to run an insert query multiple times; it asks for ID and name only one time ( if value in counter is > than 1 ).

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

Let me explain with the help of an example :-

Say I put value 2 in counter. With this it should ask me for ID and name twice but it only asks once, and it copies the values I entered for the ID and name into table test twice.

How can I fix this? If I can't then please suggest alternative code which will fix my problem.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The substitution variables &counter, &id and &name are each evaluated once, when the PL/SQL block is compiled - not as it is being executed.

The variables are not, and cannot be, re-evaluated or re-promoted within the PL/SQL block. The block is executed as a single unit within the database - once it has been submitted for execution it is independent of the client, which just waits for it to complete (unless you interrupt it, which the client also handles). PL/SQL is not an interactive language, and you shouldn't confuse client functionality (e.g. substitution variables) with SQL or PL/SQL functionality.


Just for fun, you could generate a script based on counter which does the appropriate number of prompts for IDs and names, and gets them into a format that could be used by a simple insert:

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;

That creates a file called prompter.sql (I've put it in /tmp; put it somewhere suitable for your environment!); with the 'number of value pairs' prompt answered as 2 that temporary script would look contain:

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

That temporary script is then run with @, prompting the user for all those individual values. And then table collections built from the combined substitution variables are used in a select, which is used by the insert.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...