1

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: table server.DB_Table is mutating, trigger/function may not see it ORA-04088: トリガー'server.SEND_EMAIL'の実行中にエラーが発生しました

ここに画像の説明を入力

4

1 に答える 1

4

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

  1. UPDATEトリガーがアクティブ化されているテーブルはできません。代わりに、次を使用して値を設定する必要があります:new.EMAIL_NOTIFICATION := 1;
  2. SELECTトリガーがアクティブ化されているテーブルはできません。これは論理的に意味がありません。これが、「mutating table」エラーが発生する理由です。テーブルが変化 (変異) していて、それを読み取りたい場合、あいまいな結果が生成されます。自律的なトランザクションでこれを回避しないでください。どこかの誰かがあなたにこの提案をするでしょう。それは自分自身をさらに深く掘り下げることになります。
  3. 明示カーソルは必要ありません。明確さと単純さのために、暗黙的なものを使用してください。

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

より良い計画

  1. トリガーでメール リクエストをテーブルに配置します。これらの電子メールをバックグラウンドで電子メール サーバーに送信するジョブを頻繁に実行して、ユーザーが待たないようにします。
  2. トリガーでメールのようなメッセージをキューに入れます。...という仕事をしてください。
  3. トリガーを完全に回避します。これらのレコードを識別するジョブを作成するだけで....
于 2012-04-11T14:34:30.560 に答える