2012-04-11 3 views
1

Я пишу триггер для базы данных Oracle, чтобы отправить электронное письмо, а затем обновить столбец для этой записи, подтвердив, что письмо отправлено. Мне было рекомендовано создать курсор для извлечения каждой строки, затем собрать информацию для электронной почты, отправить электронное письмо, обновить запись, а затем повторить в цикле. Код ниже - это то, что у меня есть до сих пор.Oracle DB: Email Trigger

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.DB_Table мутирует, триггер/функция не может увидеть ее ORA-06512: на "server.SEND_EMAIL", строка 15 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 таблицу, на которой активируется триггер. Это логически не имеет смысла. Вот почему вы получаете ошибку «mutating table». Таблица меняется (mutatiing), и вы хотите ее прочитать, что приведет к неоднозначным результатам. НЕ ИСКАЙТЕ ЭТО С АВТОНОМНОЙ ОПЕРАЦИЕЙ. Кто-то где-то собирается дать вам это предложение. Это еще больше углубится в дыру.
  3. Нет необходимости в явном курсоре. Для ясности и простоты используйте неявный.

В целом, это ужасная идея. Для такой цели вы действительно не хотите этого делать. Подумайте об этом, пользователь вставляет или обновляет и должен ждать, пока база данных отправит все необходимые электронные письма. Если есть какие-либо исключения, возникающие в триггере, транзакция терпит неудачу, и вам нужно отступить.

Лучшие планы

  1. Имеют место запуска на запросы по электронной почте в таблицу. У вас есть работа, которая выполняется часто, чтобы отправить эти письма на сервер электронной почты в фоновом режиме, чтобы пользователь не дождался.
  2. Имейте триггер, чтобы отправить по электронной почте сообщения в очередь. У вас есть работа, которая ...
  3. Избегайте спускового крючка полностью. Просто выполните работу, которая идентифицирует эти записи и ...