Oracle DB:电子邮件触发器

Oracle DB:电子邮件触发器,oracle,Oracle,我正在为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_TAB

我正在为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:表服务器.DB_表正在发生变化,触发器/函数可能无法看到它ORA-06512:在服务器上。发送_电子邮件,第15行ORA-06512:在服务器上。发送_电子邮件,第18行ORA-04088:执行触发器“server.SEND_EMAIL”时出错

我提供这些解决方案

无法更新激活触发器的表。您应该改为使用:new.EMAIL_NOTIFICATION:=1; 您不能选择激活触发器的表。这在逻辑上没有意义。这就是你得到一个变异表错误的原因。表正在发生变化,您希望读取它,这将产生不明确的结果。不要使用自治事务处理此问题。某个地方的人会给你这个建议。那会把你自己挖得更深。 不需要显式游标。为了清晰和简单,请使用隐式。 总的来说,这是一个糟糕的想法。为了这样的目的,你真的不想这样做。想想看,用户执行插入或更新操作,并且必须等待数据库发送所有必要的电子邮件。如果在触发器中引发任何异常,事务将失败,您必须回滚

更好的计划

让触发器将电子邮件请求放入表中。有一个经常运行的作业,在后台将这些电子邮件发送到电子邮件服务器,这样用户就不用等待了。 让触发器将类似电子邮件的消息放入队列。有一份。。。。 完全避免触发。只要有一份工作来识别这些记录,然后。。。。 我提供这些解决方案

无法更新激活触发器的表。您应该改为使用:new.EMAIL_NOTIFICATION:=1; 您不能选择激活触发器的表。这在逻辑上没有意义。这就是你得到一个变异表错误的原因。表正在发生变化,您希望读取它,这将产生不明确的结果。不要使用自治事务处理此问题。某个地方的人会给你这个建议。那会把你自己挖得更深。 不需要显式游标。为了清晰和简单,请使用隐式。 总的来说,这是一个糟糕的想法。为了这样的目的,你真的不想这样做。想想看,用户执行插入或更新操作,并且必须等待数据库发送所有必要的电子邮件。如果在触发器中引发任何异常,事务将失败,您必须回滚

更好的计划

让触发器将电子邮件请求放入表中。有一个经常运行的作业,在后台将这些电子邮件发送到电子邮件服务器,这样用户就不用等待了。 让触发器将类似电子邮件的消息放入队列。有一份。。。。 完全避免触发。只要有一份工作来识别这些记录,然后。。。。
@Ben触发器编译但不工作。我得到了我上面添加的错误。@Ben触发器已编译但不起作用。我得到了上面添加的错误。