Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Przejdź przez pętlę, aby znaleźć powtarzające się nazwy

Nie rób w tym celu pętli w pętlach w PL/SQL - użyj SQL, aby uzyskać dane gotowe do użycia.

Najpierw tworzymy twoją tabelę z danymi testowymi (zgaduję typy danych - zastępujesz własnymi) :

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
/

Co chcemy wysłać do mail_send procedura dla każdego product_holder to kolekcja (tablica) zawierająca product_no i product_catalogue . Więc najpierw typ, który zawiera te dwa elementy:

create type t_prod_cat_no as object (
   product_no        varchar2(10)
 , product_catalogue varchar2(10)
)
/

A następnie zagnieżdżony typ tabeli (typ kolekcji) tego typu:

create type t_prod_cat_no_table as
   table of t_prod_cat_no
/

Procedura mail_send wtedy należy zaakceptować product_holder oraz typ kolekcji:

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;
/

(Po prostu używam dbms_output do symulacji tworzenia poczty.)

Następnie możesz w SQL wykonać group by product_holder i niech SQL wygeneruje kolekcję zawierającą dane:

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;
/

Wynikiem powyższego bloku będzie:

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

Robienie tego w SQL za pomocą GROUP BY daje wszystko w jednym wywołaniu, od PL/SQL do SQL, co jest o wiele bardziej wydajne niż pierwsze wywołanie w celu uzyskania odrębnego zestawu product_holder , pętla nad tym, a następnie jedno wywołanie na product_holder aby otrzymać produkty dla każdego posiadacza.

AKTUALIZACJA:

Dodano order by do collect funkcji w powyższym kodzie, aby pokazać, że masz kontrolę nad kolejnością wypełniania danych w kolekcji.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Używanie parametrów z połączeniem Oracle ODBC

  2. Jak wyświetlić wiodące zera w wielu wyroczniach?

  3. Procedura PL/SQL została pomyślnie zakończona, ale nic nie pokazuje

  4. Tabela utworzona w procedurze zostaje usunięta, pojawia się błąd kompilacji procedury

  5. Utwórz tabelę Oracle z włączonym automatycznym zatwierdzaniem