2012-04-11 14 views
1

Oracle DBが電子メールを送信し、その電子メールが送信されたことを認識するレコードの列を更新するトリガーを作成しています。カーソルを作成して各行を取得し、電子メールの情報を収集し、電子メールを送信し、レコードを更新してから、ループを繰り返すことをお勧めしました。以下のコードは私がこれまで持っていたものです。Oracle DB:電子メール・トリガー

CREATE OR REPLACE TRIGGER "SEND_EMAIL" 
After INSERT OR UPDATE OF ISSUE_ADDED_TO_ALM ON DB_TABLE FOR EACH ROW 

DECLARE 
    l_table DB_TABLE%rowtype; 
    l_body varchar2(4000); 
    l_to_address varchar2(2000); 
    l_from varchar2(200); 
    l_name varchar2(100); 
    l_summary varchar2(1000); 
    l_description varchar2(4000); 
    l_ALM_ID varchar2(100); 
    l_subject varchar2(400); 
    l_added_to_alm varchar2(200); 
    l_SID varchar2(200); 

CURSOR cur_ADDED_TO_ALM IS 
select * FROM DB_TABLE where ISSUE_ADDED_TO_ALM = '1' and EMAIL_NOTIFICATION = '0'; 

BEGIN 
OPEN cur_ADDED_TO_ALM; 
LOOP 
Fetch cur_ADDED_TO_ALM into l_table; 
Exit when cur_ADDED_TO_ALM%NOTFOUND; 


l_from := 'Data Quality IMS Team'; 

select ISSUE_REQUESTER into l_SID from DB_TABLE; 

select emp_email_name,concat(concat(emp_first_name,' '),emp_last_name) into l_to_address, l_name from telephone_book where emp_id = l_SID; 

select ISSUE_SUMMARY,ISSUE_DESCRIPTION,ALM_ISSUE_ID into l_summary, l_description, l_ALM_ID from DB_TABLE where ISSUE_ADDED_TO_ALM = '1' and EMAIL_NOTIFICATION = '0'; 

l_subject := l_ALM_ID + 'Request has been created.'; 


l_body := '<style type="text/css"> 
p{font-family: Calibri, Arial, Helvetica, sans-serif; 
font-size:12pt; 
margin-left:30px; 
} 
</style>'; 

l_body := l_body || '<p>Your request has been created.</p>'; 
l_body := l_body || '<p>Data Quality Center received the following request:</p>'; 
l_body := l_body || '<p>Request ID: '|| l_ALM_ID ||'</p>'; 
l_body := l_body || '<p>Request Title: '|| l_summary||'</p>'; 
l_body := l_body || '<p>Request Description: '|| l_description||'</p>'; 

    HTMLDB_MAIL.SEND(
    P_TO  => l_to_address, 
    P_FROM  => l_from, 
    P_BODY  => l_body, 
    P_BODY_HTML => l_body, 
    P_SUBJ  => l_subject); 


    wwv_flow_mail.push_queue(
    P_SMTP_HOSTNAME => 'mail.sever_name.net', 
    P_SMTP_PORTNO => '5' 
    ); 

END LOOP; 

update DB_TABLE set EMAIL_NOTIFICATION = '1' where ALM_ISSUE_ID = l_ALM_ID 

IF cur_ADDED_TO_ALM%ISOPEN then 
CLOSE cur_ADDED_TO_ALM; 
END IF; 
end; 

は、私は次のエラーを取得する: ORA-04091: "server.SEND_EMAIL"、行15 ORA-06512で:テーブルserver.DB_Tableが変異され、トリガー/関数はORA-06512がそれを見ていないことで、 "server.SEND_EMAIL"、行18 ORA-04088:トリガーの実行中にエラーが 'server.SEND_EMAIL'

enter image description here

+1

あなたの質問は..ですか? – Ben

+0

@Benトリガーはコンパイルされますが動作しません。上記で追加したエラーが発生しています。 –

答えて

4

私はこれらのソリューションを提供します。

  1. トリガーがアクティブになっているテーブルはUPDATEできません。代わりに値を設定する必要があります:new.EMAIL_NOTIFICATION := 1;
  2. SELECTトリガーがアクティブになっているテーブルを使用することはできません。これは理にかなっていません。これが、あなたが「テーブルの変異」を起こしている理由です。テーブルが変化している(突然変異している)あなたがそれを読んで欲しい。あいまいな結果が出る。 自律的な取引でこれを回避しないでください。誰かがあなたにこの提案をするつもりです。それは自分自身を穴の中にさらに深く掘り下げるでしょう。
  3. 明示カーソルは必要ありません。明快さと簡潔さのために暗黙のものを使用してください。

全体として、これはひどい考えです。このような目的のために、あなたは本当にこのようにしたくありません。ユーザーが挿入または更新を行い、データベースが必要なすべての電子メールを送信するまで待つ必要があります。トリガで発生した例外がある場合、トランザクションは失敗し、ロールバックする必要があります。

より良い計画

  1. は、トリガ場所テーブルへの電子メールの要求を持っています。バックグラウンドでこれらの電子メールを電子メールサーバーに送信してユーザーが待たないように頻繁に実行される仕事をしてください。
  2. トリガーに電子メールのようなメッセージをキューに入れるようにします。仕事をしている....
  3. トリガーは完全に避けてください。これらのレコードを特定して仕事をしてください。
関連する問題