I have a pl/sql query and I want it's output to be sent in email in CSV format straightaway. I have no directory to first create and save a CSV file and then pick it up to send as an attachment.
Please help with your inputs as I am not able to get away.
Regards,
Sachin
Finally figured out a solution with the help of pointers received and providing the same to further help in case someone else needs in future.
My problem was that I was mostly seeing the examples where i could either save the file on a directory or pick the file from a directory to send as an attchment but I had no provision of directory and I wanted query result to be put in CSV and sent in email dynamically. So here is the complete solution.
CREATE OR REPLACE PROCEDURE SEND_CSV_ATTACHMENT AS
v_sender VARCHAR2(130);
v_recipients VARCHAR2(4000);
v_cc VARCHAR2(4000);
v_bcc VARCHAR2(2000);
v_subj VARCHAR2(200);
v_msg CLOB;
v_mime VARCHAR2(40);
v_tbl VARCHAR2(20000);
c_cr_lf CONSTANT CHAR (2) := (CHR (13) || CHR (10)); -- Carriage Return/Line Feed characters for formatting text emails
v_loop_count PLS_INTEGER := 0;
v_attachment CLOB;
v_block_qry VARCHAR2(3000);
v_block_row VARCHAR2(6000);
TYPE bl_cur IS REF CURSOR;
v_result bl_cur;
v_rowcount NUMBER;
errMsg VARCHAR2(15000);
BEGIN
v_sender := 'somesender#xyzcommunications.com';
SELECT NVL(EMAIL_LIST, 'someone#abcd.com')
FROM
(
SELECT LISTAGG(EMAIL_ID, ',') WITHIN GROUP (ORDER BY EMAIL_ID) AS EMAIL_LIST FROM RECIPEINTS_TABLE WHERE SEND_TO = 1 AND IS_ACTIVE = 1
);
SELECT NVL(EMAIL_LIST, 'someone#abcd.com')
FROM
(
SELECT LISTAGG(EMAIL_ID, ',') WITHIN GROUP (ORDER BY EMAIL_ID) AS EMAIL_LIST FROM RECIPEINTS_TABLE WHERE SEND_CC = 1 AND IS_ACTIVE = 1
);
v_bcc := 'someone#abcd.com';
-- Generate attachment - Begin
v_attachment := '"COL1", "COL2"' || CHR(13) || CHR(10);
v_block_qry := 'SELECT ''"'' || COL1 || ''", "'' || COL2 || ''"'' AS ROWTXT
FROM MY_TABLE';
OPEN v_result FOR v_block_qry;
LOOP
v_rowcount := v_result%ROWCOUNT;
FETCH v_result INTO v_block_row;
EXIT WHEN v_result%NOTFOUND;
v_attachment := v_attachment || v_block_row || chr(13) || chr(10);
END LOOP;
CLOSE v_result;
-- Generate attachment - End
v_subj:= 'MAIL_SUBJECT ' || TO_CHAR(TRUNC(SYSDATE-1), 'YYYY-MM-DD');
UTL_MAIL.send_attach_varchar2(sender => v_sender,
recipients => v_recipients,
cc => v_cc,
bcc => v_bcc,
subject => v_subj,
message => v_msg,
mime_type => 'text/html; charset=us-ascii', -- send html e-mail
attachment => v_attachment,
att_inline => FALSE,
att_filename => 'Change_Report' || TO_CHAR(TRUNC(SYSDATE-1), 'YYYY-MM-DD') || '.csv');
EXCEPTION
WHEN OTHERS THEN
errMsg := SQLERRM;
SEND_MAIL_HTML ('someone#abcd.com', NULL, NULL, errMsg, 'SEND_MAIL ERROR: ' || errMsg);
END SEND_CSV_ATTACHMENT;
You may create such a procedure :
create or replace procedure prFileSend is
v_mail_owner varchar2(100):='myname#someComp.com';
v_url varchar2(4000);
v_rep varchar2(4000);
delimiter varchar2(1) := chr(38);
begin
for c in ( select * from myTable )
loop
begin
v_url := 'http://www.mycompany.com/einfo/default.aspx?email='||c.email || delimiter || 'p1=' || c.col1 || delimiter ||'p2='||c.col2;
v_rep := utl_http.request(utl_url.escape(v_url, false,'ISO-8859-9'));
end;
end loop;
exception
when others then
prErrorMsgSend(v_mail_owner,'Error : ' || sqlerrm); -- a function like this one which sends an error message back to you.
end;
and create a scheduler job
begin
dbms_scheduler.create_job (
job_name => 'jbFileSend ',
job_type => 'STORED_PROCEDURE',
job_action => 'prFileSend',
start_date => '22-jan-2018 09:00:00 am',
repeat_interval => 'FREQ=DAILY; INTERVAL=1',
comments => 'Sending Every day'
enabled => true);
end;
working every day as an example.
Related
I am sending emails true oracle apex which works fine. what i need however is to have an sql count statement in the message of the email.
what i have is
begin
utl_mail.send(sender => 'a#test.com',
recipients =>'a#test.com',
subject => 'FileRequest',
message => 'select count(filenumber) where status is assigned' files from registry '||:p5_filenumber ||''||' ' ||:p5_filename || ' has now been assigned to the ' || :p5_department || '');
end;
which obviously is not working
what i will like to see is
begin
utl_mail.send(sender => 'a#test.com',
recipients =>'a#test.com',
subject => 'FileRequest',
message => 5 files from registry '||:p5_filenumber ||''||' ' ||:p5_filename || ' has now been assigned to the ' || :p5_department || '');
end;
Compute the value BEFORE sending the mail. Something like this:
declare
l_cnt number;
l_msg varchar2(200);
begin
-- select number you're interested in
select count(*)
into l_cnt
from some_table
where some_conditions;
-- compose the message
l_msg := l_cnt ||' files from registry ...';
-- send mail
utl_mail.send(sender => 'a#test.com',
recipients => 'a#test.com',
subject => 'FileRequest',
message => l_msg);
end;
I have a column Value Méroné in my Oracle DB.
We are writing it to a csv file using utl_file package.Since this value has a special character we have used convert function to change the character coding to remove the junk character while writing. So the convert function goes like this-
convert(REC.DT25, 'WE8DEC'). But the problem now is that the value is coming as only Méron and the last character is missing. I have tried everything from changing it to different character encoding, but still no luck. Could you please help?
The code is as follows
CREATE OR REPLACE PROCEDURE SAMPLE_MERONE AS
CREATE OR REPLACE PROCEDURE SAMPLE_MERONE AS
CURSOR C1 IS select * from gsal_mosaic_prf_output where CS46SIGFORMALNAME
LIKE 'Lt. Jowens Méroné' AND ID_NUMBER='8-13678728';
MERONE_FILE UTL_FILE.FILE_TYPE;
V_MERONE_FILE VARCHAR2(300);
BEGIN
V_MERONE_FILE := 'MREONE_FILE.csv';
MERONE_FILE := UTL_FILE.FOPEN ( 'GSAL_PRF',V_MERONE_FILE,'w',32767) ;
IF UTL_FILE.IS_OPEN(MERONE_FILE) THEN
FOR REC IN C1
LOOP
UTL_FILE.PUT_LINE(MERONE_FILE,'"'||REC.ID_NUMBER||'","'||
REC.GROUP_ID||'","'||convert(REC.CS46LASTNAME,'WE8ISO8859P1',
'UTF8')||'","'||
convert(REC.CS46SIGFORMALNAME,'WE8ISO8859P1',
'UTF8')||'"',TRUE);
END LOOP;
UTL_FILE.FCLOSE ( MERONE_FILE ) ;
END IF;
END SAMPLE_MERONE;
Running the following script on a 12.2 AL32UTF8 database reproduces the issue.
declare
cursor c1 is
select lastname
,convert(lastname, 'WE8ISO8859P1','UTF8') convertedname
,dump(convert(lastname, 'WE8ISO8859P1','UTF8')) dumpconvertedname
from (select 'Lt. Jowens Méroné' as lastname
from dual);
merone_file utl_file.file_type;
v_merone_file varchar2(300);
begin
merone_file := utl_file.fopen('NGM1_PAD_IN', 'test.csv', 'w', 32767);
if utl_file.is_open(merone_file)
then
for rec in c1
loop
dbms_output.put_line(rec.lastname ||' - ' ||rec.convertedname);
dbms_output.put_line(rec.dumpconvertedname);
utl_file.put_line(merone_file
,rec.lastname || '","' ||
rec.convertedname || '"'
,true);
end loop;
utl_file.fclose(merone_file);
end if;
end;
/
Screen output:
Lt. Jowens Méroné - Lt. Jowens Méron
Typ=1 Len=17: 76,116,46,32,74,111,119,101,110,115,32,77,233,114,111,110,233
File contents:
Lt. Jowens Méroné","Lt. Jowens Méron"
The conversion changes 195 169 into character 233. You can see it as the last character in the converted string. But somehow does not make it's way into the file.
Exploring the file with a hex editor confirms this.
As a workaround you can assemble all your data into a CLOB and write it as follows. This seems to convert your data correctly.
declare
l_clob clob;
l_string varchar2(32767);
cursor c1 is
select lastname
from (select 'Lt. Jowens Méroné' as lastname
from dual);
begin
dbms_lob.createtemporary(lob_loc => l_clob, cache => true, dur => dbms_lob.call);
dbms_lob.open(lob_loc => l_clob, open_mode => dbms_lob.lob_readwrite);
for rec in c1
loop
l_string := rec.lastname || '","' || rec.lastname || '"' || chr(13) || chr(10);
dbms_lob.writeappend(lob_loc => l_clob, amount => length(l_string), buffer => l_string);
end loop;
dbms_xslprocessor.clob2file(flocation => 'NGM1_PAD_IN'
,fname => 'test2.csv'
,cl => l_clob
,csid => nls_charset_id('WE8ISO8859P1'));
end;
/
In the below PL/SQL SP Cursor output store as HTML table and send as Excel file as attachment.
But I am getting the following error, even if I take CLOB datatype:
ORA-06502: PL/SQL: numeric or value error: raw variable length too long
ORA-06512: at "SYS.UTL_MAIL", line 654
ORA-06512: at "SYS.UTL_MAIL", line 739
CREATE OR REPLACE PROCEDURE sp_send_mail_with_attch (
p_mode char,
p_message VARCHAR2 := '.',
p_subject VARCHAR2 := '.',
p_from VARCHAR2 := 'ITTEAM'
) AS
msg_from VARCHAR2(50);
msg_to VARCHAR2(4000);
message_to VARCHAR2(50);
mailhost VARCHAR2(30);
mailport VARCHAR2(20);
crlf VARCHAR2(2) := chr(13)|| chr(10);
msg_subject VARCHAR2(250);
tablehead VARCHAR2(32767);
message VARCHAR2(32767);
mainmsg VARCHAR2(32767);
v_errortext VARCHAR2(200);
v_errormsg VARCHAR2(200) := ' ';
v_error VARCHAR2(2000) := ' ';
mail_conn utl_smtp.connection;
attachment_text clob;
v_messageatt clob;
v_filedate varchar2(100);
CURSOR main_cursor IS
select customer_id,customer_name, to_char(validity_date,'DD-MON-YYYY') validity_date
FROM
(select( trunc(validity_date) - trunc(sysdate) ) datediff,
a.* from table_name a WHERE lei_flag = 'Y'
) lei;
main_cursor_var main_cursor%rowtype;
begin
SELECT a.smtpserver,a.smtpserverport,'' toaddress,'' fromaddress
into mailhost,mailport,message_to,msg_from
from emailsettingtable a
WHERE ROWNUM < 2;
msg_from := p_from;
msg_to := '';
IF p_mode = '89' THEN
dbms_output.put_line('89');
msg_to := message_to;
msg_subject := 'CUSTOMER report';
message := '<html><head></head>';
message := message || '<body>';
message := message || 'Dear Sir/Madam,<br>';
message := message || 'Please find attached of Cutomer LEI Expiry<br>';
message := message || '<table>';
v_messageatt := '<html><head></head>';
v_messageatt := v_messageatt || '<body><br>';
v_messageatt := v_messageatt || '<table>';
OPEN main_cursor;
LOOP
FETCH main_cursor INTO main_cursor_var;
EXIT WHEN
( main_cursor%notfound );
IF main_cursor%rowcount = 1 THEN
v_messageatt := v_messageatt || '<tr><th>CUSTOMER ID</th><th>CUSTOMER NAME</th><th>VALIDITY DATE</th></tr>';
END IF;
v_messageatt := v_messageatt || '<tr>';
v_messageatt := v_messageatt|| '<td>'|| main_cursor%rowcount|| '</td>';
v_messageatt := v_messageatt|| '<td>'|| main_cursor_var.customer_id|| '</td>';
v_messageatt := v_messageatt || '<td>'|| main_cursor_var.CUSTOMER_NAME||'</td>';
v_messageatt := v_messageatt || '<td>'|| main_cursor_var.validity_date||'</td>';
v_messageatt := v_messageatt || '</tr>';
attachment_text := v_messageatt;
END LOOP;
CLOSE main_cursor;
dbms_output.put_line('89');
v_messageatt := v_messageatt || '</table>';
message := message || '</table>';
message := message|| '<br>'|| 'Regards,<br>'|| 'IT Team <br><br> ';
message := message || '</body></html>';
mainmsg := message;
dbms_output.put_line(message);
END IF;
dbms_output.put_line('msg_subject-->' || msg_subject);
dbms_output.put_line('MESSAGE-->' || message);
IF p_mode = '89' THEN
--msg_subject := 'LERM Counterparty - Exposure Data Uploaded sucessfully ...';
msg_to := msg_to || 'abc#gmail.com';
END IF;
select to_char(sysdate,'DD_MON_YYYYHH24:MI:SS') into v_filedate
from dual;
sys.utl_mail.send_attach_raw(
sender => msg_from,
recipients => msg_to,
cc => '',
bcc => '',
subject => msg_subject,
message => mainmsg,
mime_type => 'text/html',
priority => 1,
attachment => utl_raw.cast_to_raw(attachment_text),
att_inline => true,
att_mime_type => 'text/plain; charset=us-ascii',
att_filename => 'filename_'|| v_filedate|| '.xls',
replyto => ''
);
dbms_output.put_line('2');
msg_to := '';
dbms_output.put_line('Send Sucessfully ........');
EXCEPTION
WHEN others THEN
v_errortext := substr(sqlerrm,1,200);
dbms_output.put_line(sqlerrm);
END;
You cannot create a HTML document (using <table>..<tr>, etc.) and convert this simple to RAW. Creating a Excel file purely in PL/SQL is quite painful, perhaps you will find a solution here on SO. One solution is to call an external Java procedure which generates the Excel sheet.
In general you can format your e-mail as HTML with well known formation capabilities or you can attach a binary Excel file.
Attachment for utl_mail.send_attach_raw is limited to 32k, it also have some other limitation. I recommend to use UTL_SMTP, this package is more complex to use but it gives you much more flexibility. Have a look at how to export data from log table to email body in oracle to see a full featured example.
I want to Send Email via gmail or yahoo host using PL_SQL, i searched in google and find SMT.Mail package but it did't work for me, Please any one can guide me how will i achieve this goal ?
CREATE OR REPLACE PROCEDURE
send_mail (sender IN VARCHAR2,
recipient IN VARCHAR2,
message IN VARCHAR2,
nStatus OUT NUMBER)
IS
mailhost VARCHAR2(30) := 'smtp.gmail.com '; -- host mail addr
mail_conn utl_smtp.connection;
BEGIN
nStatus := 0;
mail_conn := utl_smtp.open_connection(mailhost, 25);
utl_smtp.helo(mail_conn, mailhost);
utl_smtp.mail(mail_conn, sender);
utl_smtp.rcpt(mail_conn, recipient);
utl_smtp.data(mail_conn, message);
utl_smtp.quit(mail_conn);
EXCEPTION
WHEN OTHERS THEN
nStatus := SQLCODE;
END send_mail;
when i test this procedure I get: ORA-29278: SMTP transient error: 421 Service not available
You missed your authentication at the server, see AUTH Function and Procedure
However, I do not know whether gmail allows to use port 25 which is not secure by default.
My experience has been that the utl_mail package is much easier to use. Here is a silly example:
BEGIN
UTL_MAIL.send (sender => 'bighearted#somewhere.com'
, recipients => 'receiver#footballreceiver.com'
, subject => 'Goofy Messages'
, MESSAGE => 'Please don''t send any more goofy messages'
, mime_type => 'text/html; charset=us-ascii');
END;
You must set the system parameter smtp_out_server to the name of your email server.
With Oracle 11G R2 and beyond, you must set up the proper access control list (ACL) for this to work. This is the code that I use to do so.
DECLARE
-- ACL name to be used for email access reuse the same value for all
-- future calls
l_acl VARCHAR2 (30) := 'utl_smtp.xml';
-- Oracle user to be given permission to send email
l_principal VARCHAR2 (30) := 'CEAADMIN';
-- Name of email server
g_mailhost VARCHAR2 (60) := 'mail.yourserver.com';
l_cnt INTEGER;
PROCEDURE validate_smtp_server
AS
l_value v$parameter.VALUE%TYPE;
l_parameter v$parameter.name%TYPE := 'smtp_out_server';
BEGIN
SELECT VALUE
INTO l_value
FROM v$parameter
WHERE name = l_parameter;
IF l_value IS NULL
THEN
raise_application_error (
-20001
, 'Oracle parameter '
|| l_parameter
|| ' has not been set'
|| UTL_TCP.crlf
|| 'it s/b mail.yourserver.com'
);
END IF;
DBMS_OUTPUT.put_line ('parameter ' || l_parameter || ' value is ' || l_value);
END validate_smtp_server;
PROCEDURE create_if_needed (p_acl IN VARCHAR2)
AS
l_cnt INTEGER;
BEGIN
SELECT COUNT (*) c
INTO l_cnt
FROM dba_network_acls a
WHERE SUBSTR (acl, INSTR (acl, '/', -1) + 1) = p_acl;
IF l_cnt = 0
THEN
DBMS_OUTPUT.put_line ('creating acl ' || p_acl);
DBMS_NETWORK_ACL_ADMIN.create_acl (
acl => p_acl
, description => 'Allow use of utl_smtp'
, principal => l_principal
, is_grant => TRUE
, privilege => 'connect'
);
DBMS_NETWORK_ACL_ADMIN.assign_acl (acl => p_acl, HOST => g_mailhost);
COMMIT;
ELSE
DBMS_OUTPUT.put_line (p_acl || ' acl already exists');
END IF;
END create_if_needed;
PROCEDURE add_if_needed (
p_principal IN VARCHAR2
, p_acl IN VARCHAR2
)
AS
l_cnt INTEGER;
BEGIN
SELECT COUNT (*) c
INTO l_cnt
FROM dba_network_acl_privileges
WHERE SUBSTR (acl, INSTR (acl, '/', -1) + 1) = p_acl
AND principal = p_principal;
IF l_cnt = 0
THEN
DBMS_NETWORK_ACL_ADMIN.add_privilege (
acl => 'utl_smtp.xml'
, principal => p_principal
, is_grant => TRUE
, privilege => 'connect'
);
COMMIT;
DBMS_OUTPUT.put_line ('access to ' || p_acl || ' added for ' || p_principal);
ELSE
DBMS_OUTPUT.put_line (p_principal || ' already has access to ' || p_acl);
END IF;
END add_if_needed;
BEGIN
EXECUTE IMMEDIATE 'grant execute on utl_mail to ' || l_principal;
create_if_needed (p_acl => l_acl);
add_if_needed (p_principal => l_principal, p_acl => l_acl);
DBMS_OUTPUT.put_line ('Verification SQL:');
DBMS_OUTPUT.put_line (' SELECT * FROM dba_network_acls;');
DBMS_OUTPUT.put_line (' SELECT * FROM dba_network_acl_privileges;');
COMMIT;
validate_smtp_server;
END;
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 years ago.
Improve this question
I get the following error:
58/6 PLS-00103: Encountered the symbol "END" when expecting one of
the following:
begin function pragma procedure subtype type
current cursor delete
exists prior
Anyone have any idea what I am missing?
CREATE OR REPLACE PROCEDURE VALIDATE_BI_JOB_COMPLETE_PROC AS
msg SYS.XMLTYPE;
msg_props DBMS_AQ.MESSAGE_PROPERTIES_T;
msg_id RAW(16);
queue_options DBMS_AQ.ENQUEUE_OPTIONS_T;
rec_count INTEGER;
/******************************************************************************
NAME: VALIDATE_BI_JOB_COMPLETE_PROC
*******************************************************************************
BEGIN
INSERT INTO JOB_LOG
(JOB_NAME, JOB_SEQUENCE, RUN_DATE, LINE_SEQ_NO, LOG_TXT)
VALUES
($$PLSQL_UNIT, 1, SYSDATE, 1, 'Job Started at ' || to_char(sysdate, 'MM/DD/YYYY HH:MI:SS'));
COMMIT;
rec_count := 0;
SELECT COUNT(*) INTO rec_count
FROM SCHEDULED_JOBS
WHERE JOB_NAME IN ('bi_get_transactional_data', 'bi_get_reference_data') AND
CURRENTLY_PROCESSING_FLG = 'Y';
IF rec_count > 0 THEN
BEGIN
DECLARE CURSOR email IS
SELECT EMAIL_ID
FROM ERROR_EMAIL_NOTIFICATION
WHERE ACTIVE = 'Y' AND
SEVERITY_CD = 'ERROR';
vFROM VARCHAR2(30) := 'WORK_SYSTEM#XXX.COM';
vTYPE VARCHAR2(30) := 'text/plain; charset=us-ascii';
msg_body VARCHAR2(4000) := 'BI jobs are still running, please investigate.
bi_get_transactional_data, bi_get_reference_data)';
crlf CONSTANT VARCHAR2(2):= CHR(13) || CHR(10);
FOR email_rec IN email
LOOP
utl_mail.send(vFROM, email_rec.EMAIL_ID, NULL, NULL, ora_database_name || ': ' ,
msg_body, vTYPE, NULL);
END LOOP;
END;
END IF;
INSERT INTO JOB_LOG
(JOB_NAME, JOB_SEQUENCE, RUN_DATE, LINE_SEQ_NO, LOG_TXT)
VALUES
($$PLSQL_UNIT, 2, SYSDATE, 1, 'Job Ended at ' || to_char(sysdate, 'MM/DD/YYYY HH:MI:SS') ||
'. Records sent to JSSO: ' || rec_processed);
COMMIT;
-- exception processing goes here
EXCEPTION
WHEN OTHERS THEN
LOG_ERROR(
p_APP_ID => 'ORACLE',
p_SEVERITY_CD => 'ERROR',
p_ROUTINE_NAME => $$PLSQL_UNIT,
p_BACKTRACE => DBMS_UTILITY.FORMAT_ERROR_BACKTRACE,
p_SQL_CODE => SQLCODE,
p_LOG_TXT => SQLERRM,
p_HOST_ID => SYS_CONTEXT('userenv', 'host'),
p_USER_ID => SYS_CONTEXT('userenv', 'session_user'),
p_SESSION_ID => SYS_CONTEXT('userenv', 'sid'));
INSERT INTO JOB_LOG
(JOB_NAME, JOB_SEQUENCE, RUN_DATE, LINE_SEQ_NO, LOG_TXT)
VALUES
($$PLSQL_UNIT, 2, SYSDATE, 1, 'Job ABENDED at ' || to_char(sysdate, 'MM/DD/YYYY
HH:MI:SS') || '. Error condtion.');
COMMIT;
END;
/
You must move your BEGIN from the 28 line to the line 41. Instead of this:
IF rec_count > 0 THEN
BEGIN <----------------------------------------- THIS IS WRONG
DECLARE CURSOR email IS
SELECT EMAIL_ID
FROM ERROR_EMAIL_NOTIFICATION
WHERE ACTIVE = 'Y' AND
SEVERITY_CD = 'ERROR';
vFROM VARCHAR2(30) := 'WORK_SYSTEM#XXX.COM';
vTYPE VARCHAR2(30) := 'text/plain; charset=us-ascii';
msg_body VARCHAR2(4000) := 'BI jobs are still running, please investigate.
bi_get_transactional_data, bi_get_reference_data)';
crlf CONSTANT VARCHAR2(2):= CHR(13) || CHR(10);
FOR email_rec IN email
LOOP
Write this:
IF rec_count > 0 THEN
DECLARE CURSOR email IS
SELECT EMAIL_ID
FROM ERROR_EMAIL_NOTIFICATION
WHERE ACTIVE = 'Y' AND
SEVERITY_CD = 'ERROR';
vFROM VARCHAR2(30) := 'WORK_SYSTEM#XXX.COM';
vTYPE VARCHAR2(30) := 'text/plain; charset=us-ascii';
msg_body VARCHAR2(4000) := 'BI jobs are still running, please investigate.
bi_get_transactional_data, bi_get_reference_data)';
crlf CONSTANT VARCHAR2(2):= CHR(13) || CHR(10);
BEGIN <-------------------------------------------- THIS IS OK
FOR email_rec IN email
LOOP
You have an END; just before your END IF; which is causing the problem
So Oracle thinks the IF statement is not closed. Plus it will ignore all the code after the END!
IF rec_count > 0 THEN
BEGIN
DECLARE
CURSOR email IS
SELECT EMAIL_ID
FROM ERROR_EMAIL_NOTIFICATION
WHERE ACTIVE = 'Y' AND
SEVERITY_CD = 'ERROR';
vFROM VARCHAR2(30) := 'WORK_SYSTEM#XXX.COM';
vTYPE VARCHAR2(30) := 'text/plain; charset=us-ascii';
msg_body VARCHAR2(4000) := 'BI jobs are still running, please investigate.
bi_get_transactional_data, bi_get_reference_data)';
crlf CONSTANT VARCHAR2(2):= CHR(13) || CHR(10);
BEGIN
FOR email_rec IN email
LOOP
utl_mail.send(vFROM, email_rec.EMAIL_ID, NULL, NULL, ora_database_name || ': ' ,
msg_body, vTYPE, NULL);
END LOOP;
END;
END;
END IF;
--rest of the code
The problem was that, after the 'DECLARE' you need to add a 'BEGIN', and an 'END' following the 'END LOOP'. I hope you understood. Also that makes me wonder, do you need the 'BEGIN' you have added just above the 'DECLARE' there? Hope this solves it :)