Oracle
 sql >> Base de données >  >> RDS >> Oracle

Comment pouvez-vous exécuter la même requête plusieurs fois en utilisant une boucle en PL/SQL ?

Les variables de substitution &counter , &id et &name sont chacun évalués une fois, lorsque le bloc PL/SQL est compilé - pas pendant son exécution.

Les variables ne sont pas et ne peuvent pas être réévaluées ou repromues dans le bloc PL/SQL. Le bloc est exécuté comme une seule unité dans la base de données - une fois qu'il a été soumis pour exécution, il est indépendant du client, qui attend juste qu'il se termine (sauf si vous l'interrompez, ce que le client gère également). PL/SQL n'est pas un langage interactif et vous ne devez pas confondre la fonctionnalité client (par exemple, les variables de substitution) avec la fonctionnalité SQL ou PL/SQL.

Juste pour le plaisir, vous pouvez générer un script basé sur counter qui fait le nombre approprié d'invites pour les identifiants et les noms, et les met dans un format qui pourrait être utilisé par une simple insertion :

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;

Cela crée un fichier appelé prompter.sql (Je l'ai mis dans /tmp; placez-le dans un endroit adapté à votre environnement !); avec l'invite 'nombre de paires de valeurs' répondue comme 2 que le script temporaire semblerait contenir :

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

Ce script temporaire est ensuite exécuté avec @ , invitant l'utilisateur à entrer toutes ces valeurs individuelles. Ensuite, les collections de tables construites à partir des variables de substitution combinées sont utilisées dans une sélection, qui est utilisée par l'insertion.