2015-01-21 3 views
0

다음과 같은 결과가 있습니다. plsql 블록에서 레코드 및 send_email을 고객에게 전달합니다.반복 된 이름을 찾기 위해 루프를 통과합니다.

enter image description here

익명 블록

FOR i IN (SELECT product_no, product_holder,product_catalogue FROM 
product_master) 
LOOP 
mail_send('PRODMASTER',i.product_holder, i.product_no,i.product_catalogue); 
END LOOP; 
내가 한 이메일을 보내 싶습니다 product_holder 쿼리 결과에 반복 후가 아니라 여러 개의 이메일을 보내는 경우 가장 좋은 방법이 무엇인지 알고 싶습니다

관련 세부 사항. 예 : 위의 경우에서 스미스는 두 개의 이메일을 얻을 것이다 위의 접근 방식 스미스, 그래서 대신 내가 product_noproduct_catalogue 나는이 작업을 수행 할 수있는 방법

SMITH 한 이메일을 보내려는 두 번 반복된다?

+1

PL/SQL 루프 -> 행 별 행 일명 천천히 느림. SQL에서 동일한 작업을 수행 할 수있는 경우 PL/SQL에서 수행하지 마십시오. –

+0

난 그냥 생각하고, 거기에 그룹 fuction에서 사용할 수있는 몇 가지 목록 기능, 그래서 당신은 togheter 그룹화 된 각 레코드의 값을 나열 할 수 있습니까? 기본적으로 그것은 OP가 요구하는 것입니다. 그렇게하면 순수 SQL로 수행 할 수 있습니다. – tvCa

+0

테스트되지 않은 것일 수도 있습니다. http://www.williamrobertson.net/documents/one_row.html – tvCa

답변

5

PL/SQL의 루프 내에서 루프를 수행하지 마십시오. SQL을 사용하여 데이터를 사용할 수 있습니다.

먼저 우리는 (나는 데이터 유형을 추측하고있어 - 당신이 당신의 자신의로 대체) 테스트 데이터로 테이블을 만들 :

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 
/

는 우리가 각 product_holder에 대한 mail_send 절차에 보내려고하는 모음 (배열입니다)이며 product_noproduct_catalogue을 포함합니다. 그래서 처음 두 요소가 포함 된 유형 : 유형의 다음

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

그리고 중첩 된 테이블 형식 (컬렉션 타입) :

create type t_prod_cat_no_table as 
    table of t_prod_cat_no 
/

이 절차 mail_send는 다음 product_holder 및 컬렉션 형식을 받아 들여야을 :

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

(난 그냥 메일을 구축 시뮬레이션 DBMS_OUTPUT 사용합니다.)

그런 다음

당신은 SQL에서 group by product_holder을하고 SQL 데이터를 포함하는 컬렉션을 생성 할 수 있습니다

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

위의 블록의 출력이 될 것입니다 :

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

GROUP BY와 SQL에 그 일을 PL/SQL에서 SQL 로의 단일 호출에서 모든 것을 제공합니다. 이는 첫 번째 호출보다 훨씬 더 효율적이며 product_holder의 고유 한 집합을 얻고 그 루프를 반복 한 다음 product_holder에 대해 하나의 호출을 수행하여 각 소유자에 대해 제품을 얻습니다 .

UPDATE : 위의 코드에서 collect 기능

추가 order by는 데이터 수집에 채워지는 순서를 제어 할 수 있습니다 표시합니다.

1

두 개의 루프를 사용하여 각 제품 홀더마다 메일을 보낼 수 있습니다.

FOR i IN (SELECT distinct product_holder FROM 
product_master) 
LOOP 
v_products := null; 
v_catalogs := null; 
for product in (SELECT pm.product_no, pm.product_catalogue FROM 
        product_master pm where pm.product_holder = i.product_holder) 
loop 
    if v_products is null then 
     v_products := product.product_no; 
    else 
     v_products := v_products ||', ' ||product.product_no; 
    end if; 
    if v_catalogs is null then 
     v_catalogs := product.product_catalogue; 
    else 
     v_catalogs := v_catalogs ||', ' ||product.product_catalogue; 
    end if; 
end loop; 
mail_send('PRODMASTER',i.product_holder, v_products,v_catalogs); 
END LOOP; 
관련 문제