Ne faites pas de boucles dans les boucles en PL/SQL pour cela - utilisez SQL pour vous donner les données prêtes à l'emploi.
Nous créons d'abord votre table avec des données de test (je suppose que les types de données - vous remplacez par les vôtres) :
create table product_master (
product_no varchar2(10)
, product_holder varchar2(10)
, product_catalogue varchar2(10)
)
/
insert into product_master values ('1', 'SMITH', 'TEMP')
/
insert into product_master values ('2', 'SMITH', 'TEMP')
/
insert into product_master values ('3', 'HARRY', 'ARCH')
/
insert into product_master values ('4', 'TOM' , 'DEPL')
/
commit
/
Ce que nous voulons envoyer à mail_send
procédure pour chaque product_holder
est une collection (tableau) contenant product_no
et product_catalogue
. Donc d'abord un type qui contient ces deux éléments :
create type t_prod_cat_no as object (
product_no varchar2(10)
, product_catalogue varchar2(10)
)
/
Et puis un type de tableau imbriqué (type de collection) de ce type :
create type t_prod_cat_no_table as
table of t_prod_cat_no
/
La procédure mail_send
alors devrait accepter le product_holder
et le type de collecte :
create or replace procedure mail_send (
p_parameter in varchar2
, p_product_holder in varchar2
, p_product_cats_nos in t_prod_cat_no_table
)
is
begin
dbms_output.put_line('-- BEGIN '||p_parameter||' --');
dbms_output.put_line('Dear '||p_product_holder);
dbms_output.put_line('Your products are:');
for i in 1..p_product_cats_nos.count loop
dbms_output.put_line(
'Catalogue: '||p_product_cats_nos(i).product_catalogue||
' - No: '||p_product_cats_nos(i).product_no
);
end loop;
end mail_send;
/
(J'utilise simplement dbms_output pour simuler la création d'un courrier.)
Ensuite, vous pouvez en SQL faire un group by product_holder
et laissez SQL générer la collection contenant les données :
begin
for holder in (
select pm.product_holder
, cast(
collect(
t_prod_cat_no(pm.product_no,pm.product_catalogue)
order by pm.product_catalogue
, pm.product_no
) as t_prod_cat_no_table
) product_cats_nos
from product_master pm
group by pm.product_holder
order by pm.product_holder
) loop
mail_send(
'PRODMASTER'
, holder.product_holder
, holder.product_cats_nos
);
end loop;
end;
/
La sortie du bloc ci-dessus sera :
-- BEGIN PRODMASTER --
Dear HARRY
Your products are:
Catalogue: ARCH - No: 3
-- BEGIN PRODMASTER --
Dear SMITH
Your products are:
Catalogue: TEMP - No: 1
Catalogue: TEMP - No: 2
-- BEGIN PRODMASTER --
Dear TOM
Your products are:
Catalogue: DEPL - No: 4
Le faire en SQL avec un GROUP BY
vous donne tout en un seul appel de PL/SQL à SQL, ce qui est beaucoup plus efficace qu'un premier appel pour obtenir l'ensemble distinct de product_holder
, faites une boucle dessus, puis un appel par product_holder
pour obtenir les produits pour chaque titulaire.
MISE À JOUR :
Ajout de order by
à la collect
fonction dans le code ci-dessus pour montrer que vous contrôlez l'ordre dans lequel les données sont renseignées dans la collection.