How to re-design code with UTL_SMTP - Oracle Apex send mail - oracle

It's been a hard time not able to make my code to work with UTL_SMTP package.
Can some one guide me to change below code and make it work with UTL_SMTP method
I created a mailing application which sends mail to all user on their email id's with an attachment.
Took reference and I built it same exactly like this
https://blogs.oracle.com/apex/post/creating-email-campaign-app-with-oracle-apex
My Code :
declare
l_context apex_exec.t_context;
l_emailsidx pls_integer;
l_namesids pls_integer;
l_region_id number;
begin
-- Get the region id for the CUSTOMERS IR region
select region_id
into l_region_id
from apex_application_page_regions
where application_id = :APP_ID
and page_id = 1
and static_id = 'CUSTOMERS';
l_context := apex_region.open_query_context (
p_page_id => 1,
p_region_id => l_region_id );
-- Get the column positions for EMAIL and NAME columns
l_emailsidx := apex_exec.get_column_position( l_context, 'EMAIL' );
l_namesids := apex_exec.get_column_position( l_context, 'NAME' );
-- Loop throught the query of the context
while apex_exec.next_row( l_context ) loop
l_id : = apex_mail.send (
p_to => apex_exec.get_varchar2( l_context, l_emailsidx ),
p_template_static_id => 'NEW_YEAR_2020_PROMOTION_DUBAI_BRANCH',
p_placeholders => '{' ||
' "CUSTOMER":' || apex_json.stringify( apex_exec.get_varchar2( l_context, l_namesids )) ||
' ,"START_DATE":' || apex_json.stringify( :P2_START_DATE ) ||
' ,"END_DATE":' || apex_json.stringify( :P2_END_DATE ) ||
' ,"LOCATION":' || apex_json.stringify( :P2_LOCATION ) ||
' ,"NOTES":' || apex_json.stringify( :P2_NOTES ) ||
' ,"ITEMS":' || apex_json.stringify( :P2_ITEMS ) ||
' ,"MY_APPLICATION_LINK":' || apex_json.stringify( apex_mail.get_instance_url || apex_page.get_url( 1 )) ||
'}' );
end loop;
for rec in (
select filename, blob_content, mime_type
from apex_application_files
where flow_id = :APP_ID
and filename = 'apex_logo.png'
)
loop
apex_mail.add_attachment(
p_mail_id => l_id,
p_attachment => rec.blob_content,
p_filename => rec.filename,
p_mime_type => rec.mime_type);
end loop;
apex_mail_queue(
p_smtp_hostname => 'xyz.xmp.it',
p_smtp_portno => 45
)
apex_exec.close( l_context );
exception
when others then
apex_exec.close( l_context );
raise;
end;
Need to convert my above code below like this
UTL_MAIL.send (
sender => 'example#ac.cc',
recipents => 'abcexample#ac.cc',
cc => 'xyzexample#ac.cc',
subject => 'Testing',
mime_type => 'text/html',
message => 'ABC TESTING'
);
My below code does not support at my end. It throws network access denied as (ACL). Only UTL_SMTP is supported and mail is sent. But below code need to transform as above UTL_SMTP.send method
l_id : = apex_mail.send (
p_to => apex_exec.get_varchar2( l_context, l_emailsidx ),
p_template_static_id => 'NEW_YEAR_2020_PROMOTION_DUBAI_BRANCH',
p_placeholders => '{' ||
' "CUSTOMER":' || apex_json.stringify( apex_exec.get_varchar2( l_context, l_namesids )) ||
' ,"START_DATE":' || apex_json.stringify( :P2_START_DATE ) ||
' ,"END_DATE":' || apex_json.stringify( :P2_END_DATE ) ||
' ,"LOCATION":' || apex_json.stringify( :P2_LOCATION ) ||
' ,"NOTES":' || apex_json.stringify( :P2_NOTES ) ||
' ,"ITEMS":' || apex_json.stringify( :P2_ITEMS ) ||
' ,"MY_APPLICATION_LINK":' || apex_json.stringify( apex_mail.get_instance_url || apex_page.get_url( 1 )) ||
'}' );
end loop;
for rec in (
select filename, blob_content, mime_type
from apex_application_files
where flow_id = :APP_ID
and filename = 'apex_logo.png'
)
loop
apex_mail.add_attachment(
p_mail_id => l_id,
p_attachment => rec.blob_content,
p_filename => rec.filename,
p_mime_type => rec.mime_type);
end loop;
apex_mail_queue(
p_smtp_hostname => 'xyz.xmp.it',
p_smtp_portno => 45
)
Following is the YouTube followed to create the application
https://www.youtube.com/watch?v=aZQ04yjS7rQ

Related

How to catch error and store to Error table | PL/SQL |

I have been writing a code to achieve this but fully stuck
Need you helping hands for this scenario
I have created a application with Oracle APEX with interactive report and form in my page
My procedure to sent mail
CREATE OR REPLACE PROCEDURE send_mail (p_to IN VARCHAR2,
p_from IN VARCHAR2,
p_subject IN VARCHAR2,
p_html_msg IN VARCHAR2 DEFAULT NULL,
p_smtp_host IN VARCHAR2,
p_smtp_port IN NUMBER DEFAULT 25)
AS
l_mail_conn UTL_SMTP.connection;
l_boundary VARCHAR2(50) := '----=*#abc1234321cba#*=';
BEGIN
l_mail_conn := UTL_SMTP.open_connection(p_smtp_host, p_smtp_port);
UTL_SMTP.helo(l_mail_conn, p_smtp_host);
UTL_SMTP.mail(l_mail_conn, p_from);
UTL_SMTP.rcpt(l_mail_conn, p_to);
UTL_SMTP.open_data(l_mail_conn);
UTL_SMTP.write_data(l_mail_conn, 'Date: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, 'To: ' || p_to || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, 'From: ' || p_from || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, 'Subject: ' || p_subject || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, 'Reply-To: ' || p_from || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, 'MIME-Version: 1.0' || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, 'Content-Type: multipart/alternative; boundary="' || l_boundary || '"' || UTL_TCP.crlf || UTL_TCP.crlf);
IF p_html_msg IS NOT NULL THEN
UTL_SMTP.write_data(l_mail_conn, '--' || l_boundary || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, 'Content-Type: text/html; charset="iso-8859-1"' || UTL_TCP.crlf || UTL_TCP.crlf);
UTL_SMTP.write_data(l_mail_conn, p_html_msg);
UTL_SMTP.write_data(l_mail_conn, UTL_TCP.crlf || UTL_TCP.crlf);
END IF;
UTL_SMTP.write_data(l_mail_conn, '--' || l_boundary || '--' || UTL_TCP.crlf);
UTL_SMTP.close_data(l_mail_conn);
UTL_SMTP.quit(l_mail_conn);
END;
/
On send mail button click my below code run perfectly
declare
l_context apex_exec.t_context;
l_emailsidx pls_integer;
l_namesids pls_integer;
l_region_id number;
l_html VARCHAR2(32767);
begin
select region_id
into l_region_id
from apex_application_page_regions
where application_id = :APP_ID
and page_id = 1
and static_id = 'CUSTOMERS';
l_context := apex_region.open_query_context (
p_page_id => 1,
p_region_id => l_region_id );
-- Get the column positions for EMAIL and NAME columns
l_emailsidx := apex_exec.get_column_position( l_context, 'EMAIL' );
l_namesids := apex_exec.get_column_position( l_context, 'NAME' );
while apex_exec.next_row( l_context ) loop
send_mail(
p_to => apex_exec.get_varchar2( l_context, l_emailsidx ),
p_from => 'admin#mycompany.com',
p_subject => :P2_SUBJECT,
p_html_msg => :P3_HTML,
p_smtp_host => 'smtp.mycompany.com');
Exception
when OTHERS THEN
// log my error to ERROR table
CONTINUE;
end loop;
apex_exec.close( l_context );
exception
when others then
apex_exec.close( l_context );
raise;
end;
But if any email id is invalid and my UTL SMTP not able to send mail it throws an error and I want to catch that error -> store to my below error table with email id
create table employee_error(
emailid clob,
error_msg clob
);
First code try
Exception
when OTHERS THEN
Insert into employee_error values(p_to,sqlerr);
CONTINUE;
Second code try : I tried this one also but it thrown me error : ORA-06550
while apex_exec.next_row( l_context ) loop
begin
send_mail(
p_to => apex_exec.get_varchar2( l_context, l_emailsidx ),
p_from => 'admin#mycompany.com',
p_subject => :P2_SUBJECT,
p_html_msg => :P3_HTML,
p_smtp_host => 'smtp.mycompany.com');
Exception
when OTHERS THEN
Insert into employee_error (emailid, error_msg)
values
(apex_exec.get_varchar2( l_context, l_emailsidx ), sqlerrm);
end;
end loop;
When I tried with second code I got below error
ORA-06550: column not allowed , SQL statement ignored
My processing of sending mail should not stop even if error occur so
I added continue to my exception.
So that log the error to error table and continue picking next id to trigger mail
You're quite close - just embed another BEGIN-EXCEPTION-END block into the loop. Something like this:
while apex_exec.next_row( l_context ) loop
begin
send_mail(
p_to => apex_exec.get_varchar2( l_context, l_emailsidx ),
p_from => 'admin#mycompany.com',
p_subject => :P2_SUBJECT,
p_html_msg => :P3_HTML,
p_smtp_host => 'smtp.mycompany.com');
Exception
when OTHERS THEN
Insert into employee_error (emailid, error_msg)
values
(apex_exec.get_varchar2( l_context, l_emailsidx ), sqlerrm);
end;
end loop;
I done like this by taking reference from author #littlefoot and it worked
declare
l_context apex_exec.t_context;
l_emailsidx pls_integer;
l_namesids pls_integer;
l_region_id number;
l_html VARCHAR2(32767);
v_errm varchar2(4000 char);
v_email varchar2(4000 char);
begin
select region_id
into l_region_id
from apex_application_page_regions
where application_id = :APP_ID
and page_id = 1
and static_id = 'CUSTOMERS';
l_context := apex_region.open_query_context (
p_page_id => 1,
p_region_id => l_region_id );
-- Get the column positions for EMAIL and NAME columns
l_emailsidx := apex_exec.get_column_position( l_context, 'EMAIL' );
l_namesids := apex_exec.get_column_position( l_context, 'NAME' );
while apex_exec.next_row( l_context ) loop
begin
send_mail(
p_to => apex_exec.get_varchar2( l_context, l_emailsidx ),
p_from => 'admin#mycompany.com',
p_subject => :P2_SUBJECT,
p_html_msg => :P3_HTML,
p_smtp_host => 'smtp.mycompany.com');
Exception
when OTHERS THEN
v_errm := sqlerrm;
v_email := apex_exec.get_varchar2( l_context, l_emailsidx );
Insert into employee_error values (v_errm ,v_email);
end;
end loop;
apex_exec.close( l_context );
exception
when others then
apex_exec.close( l_context );
raise;
end;
You need to use autonomous transactions for logging capabilities. It will not interrupt your flow logic and will keep logged entries in case of rollback.
create table log_table (
dttm timestamp default systimestamp,
err_code int,
err_message varchar2(1000)
)
create table t (
dttm timestamp default systimestamp,
val int
)
create procedure log_error (
code int,
msg varchar2
)
as
pragma autonomous_transaction;
begin
insert into log_table (dttm, err_code, err_message)
values(systimestamp, code, msg);
commit;
end;
/
create procedure test (
p_iter int,
p_err_stop int default null
)
as
err_cnt int := 0;
begin
for i in 1..p_iter loop
begin
if mod(i, 2) = 0 then
err_cnt := err_cnt + 1;
raise_application_error(
-20001,
i
);
end if;
insert into t (val)
values (i);
exception
when others then
log_error(sqlcode, sqlerrm);
if err_cnt > p_err_stop then
/*Stop execution*/
raise_application_error(-20002, 'Too many errors');
end if;
end;
end loop;
end;
/
begin
test(10);
commit;
test(10, 2);
commit;
end;/
ORA-20002: Too many errors
ORA-06512: at "FIDDLE_TBTPMHPKCNYEUKUQEFOW.TEST", line 26
ORA-06512: at line 4
select *
from log_table
DTTM | ERR_CODE | ERR_MESSAGE
:------------------------- | -------: | :------------
2022-06-19 11:15:49.761825 | -20001 | ORA-20001: 2
2022-06-19 11:15:49.762820 | -20001 | ORA-20001: 4
2022-06-19 11:15:49.763268 | -20001 | ORA-20001: 6
2022-06-19 11:15:49.763810 | -20001 | ORA-20001: 8
2022-06-19 11:15:49.764210 | -20001 | ORA-20001: 10
2022-06-19 11:15:49.765069 | -20001 | ORA-20001: 2
2022-06-19 11:15:49.765624 | -20001 | ORA-20001: 4
2022-06-19 11:15:49.766282 | -20001 | ORA-20001: 6
select *
from t
DTTM | VAL
:------------------------- | --:
2022-06-19 11:15:49.754656 | 1
2022-06-19 11:15:49.762612 | 3
2022-06-19 11:15:49.763093 | 5
2022-06-19 11:15:49.763500 | 7
2022-06-19 11:15:49.764034 | 9
db<>fiddle here

how to make dbms_scheduler.create_job configurable?

Rather than hard-coding values dbms_scheduler.create_job repaeat_interval, i'd like to make it configurable. Therefore, I have created a new table that allows the repeat_interval from the job to be configured.
Procedure below takes the column as input parameters:
PROCEDURE scheduled_job IS
v_start_date swpurge_job_config.start_date%TYPE;
v_freq swpurge_job_config.freq%TYPE;
v_byday swpurge_job_config.byday%TYPE;
v_byhour swpurge_job_config.byhour%TYPE;
v_byminute swpurge_job_config.byminute%TYPE;
v_bysecond swpurge_job_config.bysecond%TYPE;
v_end_date swpurge_job_config.end_date%TYPE;
BEGIN
SELECT start_date
,freq
,byday
,byhour
,byminute
,bysecond
,end_date
INTO v_start_date
,v_freq
,v_byday
,v_byhour
,v_byminute
,v_bysecond
,v_end_date
FROM swpurge_job_config;
dbms_scheduler.create_job(job_name => 'Purge_MW_Log_Data'
,job_type => 'STORED_PROCEDURE'
,job_action => 'DBA_UTILS_OWNER.PURGE_TABLES'
,start_date => 'SYSTIMESTAMP'
,repeat_interval => 'freq' || '=' ||
v_freq || '; ' ||
'byday' || '=' ||
v_byday || '; ' ||
'byhour' || '=' ||
v_byhour || '; ' ||
'byminute' || '=' ||
v_byminute || '; ' ||
'bysecond' || '=' ||
v_bysecond || ';'
,end_date => NULL
,enabled => TRUE
,auto_drop => FALSE
,comments => 'runs weekly and looks for partitions that needs to be purged');
END scheduled_job;
Not sure how else to go about this. Any help is appreciated.
error messages:
ORA-01858: a non-numeric character was found where a numeric was expected
ORA-06512: at "DBA_UTILS_OWNER.SWPURGE", line 450 > "dbms_scheduler.create_job(job_name => 'Purge_MW_Log_Data'"
DECLARE
PROCEDURE scheduled_job IS
v_start_date swpurge_job_config.start_date%TYPE;
v_freq swpurge_job_config.freq%TYPE;
v_byday swpurge_job_config.byday%TYPE;
v_byhour swpurge_job_config.byhour%TYPE;
v_byminute swpurge_job_config.byminute%TYPE;
v_bysecond swpurge_job_config.bysecond%TYPE;
--v_end_date swpurge_job_config.end_date%TYPE;
BEGIN
SELECT start_date
,freq
,byday
,byhour
,byminute
,bysecond
-- ,end_date
INTO v_start_date
,v_freq
,v_byday
,v_byhour
,v_byminute
,v_bysecond
-- ,v_end_date
FROM swpurge_job_config;
dbms_scheduler.create_job(job_name => 'Purge_MW_Log_Data'
,job_type => 'STORED_PROCEDURE'
,job_action => 'OWNER.PROCEDURE'
,start_date => v_start_date
,repeat_interval => 'freq' || '=' ||
v_freq || '; ' ||
'byday' || '=' ||
v_byday || '; ' ||
'byhour' || '=' ||
v_byhour || '; ' ||
'byminute' || '=' ||
v_byminute || '; ' ||
'bysecond' || '=' ||
v_bysecond || ';'
,end_date => NULL
,enabled => TRUE
,auto_drop => FALSE
,comments => 'something');
END scheduled_job;
BEGIN
scheduled_job();
END;
/
Issue was the single quotes around start_date. Another important thing to note is v_end_date is not allowed to be parsed in as a parameter in the dbms_scheduler (not sure why) however, this is good enough for me.

Send SQL query output as CSV attachment (pl/sql)

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.

Dynamicly Fill Array From Table at PL/SQL?

i need to pass array values dynamic at this PL/SQL CODE But the Array Just See The First Value the code : Hint( The code is big so i cut it at the issue part)please
if you need more information Kindly Ask me,Here is my try to pass it Dynamic.
Variable fill code:
FOR ET IN (SELECT EMAIL
FROM XX_INTERCO_SYS_CON
WHERE ACC_NO = Q.ACC_NO AND TYPE = 'TO')
LOOP
IF P_TO IS NOT NULL
THEN
P_TO := P_TO || ',''' || ET.EMAIL||'''';
ELSE
P_TO := ''''||ET.EMAIL||'''';
END IF;
END LOOP;
FOR EC IN (SELECT EMAIL
FROM XX_INTERCO_SYS_CON
WHERE ACC_NO = Q.ACC_NO AND TYPE = 'CC')
LOOP
IF P_CC IS NOT NULL
THEN
P_CC := P_CC || ',''' || EC.EMAIL||'''';
ELSE
P_CC := ''''||EC.EMAIL||'''';
END IF;
END LOOP;
The Array fill part :
XX_MAIL_PKG.SEND (P_FROM => P_FROM,
P_TO => XX_MAIL_PKG.ARRAY ( P_TO),
P_CC => XX_MAIL_PKG.ARRAY (P_CC),
P_SUBJECT => 'test',
P_HTML_MSG => P_HTML_OUTPUT,
P_SMTP_HOST => P_SMTP_HOST,
P_SMTP_PORT => P_SMTP_PORT,
P_TEXT_MSG => NULL,
X_ERR_MSG => X_ERR_MSG);
COMMIT;
DBMS_OUTPUT.PUT_LINE (X_ERR_MSG);
You appear to be using collections - so (without knowing what is in the XX_MAIL_PKG package) you could try this:
DECLARE
V_TO XX_MAIL_PKG.ARRAY;
V_CC XX_MAIL_PKG.ARRAY;
BEGIN
SELECT EMAIL
BULK COLLECT INTO V_TO
FROM XX_INTERCO_SYS_CON
WHERE ACC_NO = Q.ACC_NO AND TYPE = 'TO';
SELECT EMAIL
BULK COLLECT INTO V_CC
FROM XX_INTERCO_SYS_CON
WHERE ACC_NO = Q.ACC_NO AND TYPE = 'CC';
XX_MAIL_PKG.SEND (P_FROM => P_FROM,
P_TO => V_TO,
P_CC => V_CC,
P_SUBJECT => 'test',
P_HTML_MSG => P_HTML_OUTPUT,
P_SMTP_HOST => P_SMTP_HOST,
P_SMTP_PORT => P_SMTP_PORT,
P_TEXT_MSG => NULL,
X_ERR_MSG => X_ERR_MSG);
COMMIT;
DBMS_OUTPUT.PUT_LINE (X_ERR_MSG);
END;
/

How to execute a procedure with DBMS_SCHEDULER.CREATE_JOB procedure

I want to create a job that would drop a database object at a given date. The job created all right but the procedure is not executed. Tried executing the procedure alone and it works.
Here's the code for the create job
v_jobnam := v_objnam;
v_jobnam := DBMS_SCHEDULER.generate_job_name (v_jobnam);
v_startdate := to_timestamp(v_startdate);
select sysdate + (v_delhrs/1440)
into v_startdate
from dual;
DBMS_SCHEDULER.CREATE_JOB(job_name => v_jobnam, job_type => 'PLSQL_BLOCK', JOB_ACTION => 'BEGIN DROP_OBJ1(' || v_objnam|| ', ' || v_objtyp || ', '|| v_schema || ',' || v_objid ||'); END;', start_date => SYSTIMESTAMP, repeat_interval => 'freq=secondly; bysecond=0', end_date => NULL, enabled => TRUE, comments => 'Calls PLSQL once');
where v_delhrs is a number.
Here's the code for the procedure:
PROCEDURE DROP_OBJ1
(
p_objnam IN CHAR,
p_objtyp IN CHAR,
p_copyto IN ALL_OBJECTS.OWNER%TYPE,
p_objid IN NUMBER
)
IS
v_objnam VARCHAR2 (30);
v_objtyp VARCHAR2 (30);
v_copyto VARCHAR2 (30);
v_objid NUMBER (3);
BEGIN
v_objnam := UPPER (p_objnam);
v_objtyp := UPPER (p_objtyp);
v_copyto := UPPER (p_copyto);
v_objid := p_objid;
--v_copyby := UPPER (p_copyby);
EXECUTE IMMEDIATE ( ' DROP '
|| v_objtyp
|| ' '
|| v_copyto
|| '.'
|| v_objnam
);
EXECUTE IMMEDIATE ( ' DELETE FROM COPY_OBJ_DET WHERE OBJ_ID = '
|| v_objid
);
COMMIT;
END;
I know its a very minor problem.
Thanks in advance gurus.
Cheers!
It apears to me that you have missed some quote marks in the DBMS_JOBS setup call.
Try this:
DBMS_SCHEDULER.CREATE_JOB(job_name => v_jobnam,
job_type => 'PLSQL_BLOCK',
JOB_ACTION => 'BEGIN DROP_OBJ1(''' || v_objnam
|| ''', ''' || v_objtyp || ''', '''
|| v_schema || ''',' || v_objid
|| '); END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'freq=secondly; bysecond=0',
end_date => NULL,
enabled => TRUE,
comments => 'Calls PLSQL once');
If this is not the solution I will setup your code on a database and try it myself.

Resources