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.
Related
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
I am new to Oracle APEX, i am trying to import csv file then parse the file contents, actually we have various staging table, according to that i need to write some logic like below, can anyone please let me know how to execute plsql dynamic content in oracle apex.
DECLARE
p_TABLE_NAME VARCHAR2(50);
p_file_name VARCHAR2(255);
l_columns_item varchar2(4000);
l_ddl VARCHAR2(4000);
BEGIN
p_TABLE_NAME := :P120_TABLENAME;
p_file_name := :P120_BRO_FILENAME;
IF p_TABLE_NAME = 'DUMMY' THEN
l_columns_item := 'col001,col002,col003,col004,col005,col006,col007,col008,col009';
END IF;
l_ddl := 'select line_number,'
|| l_columns_item
|| ' '
|| 'from apex_application_temp_files f, '
|| ' table( apex_data_parser.parse(
p_content => f.blob_content,
p_add_headers_row => 'Y',
p_max_rows => 50,
p_store_profile_to_collection => 'FILE_PARSER_COLLECTION',
p_file_name => f.filename )) p '
|| 'where f.name ='''
|| p_file_name
|| '''';
execute immediate l_ddl;
RETURN l_ddl;
END;
The variable l_ddl contain below query how do i execute using oracle apex plsql dynamic content
select line_number,col001,col002,col003,col004,col005,col006,col007,col008,col009,col010,col011,col012,col013 from apex_application_temp_files f, table( apex_data_parser.parse(
p_content => f.blob_content,
p_max_rows => 50,
p_file_name => f.filename )) p where f.name ='a.csv'
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.
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.
Is there is any possibility to reset the sequence number every year automatically ? For example on 31 Dec the sequence is 3465, it should be 0001 on 1st January .
For now I reset it by below query manually
select p_seq_name.nextval from dual;
alter sequence p_seq_name increment by -3465 minvalue 0;
select p_seq_name.nextval from dual;
alter sequence p_seq_name increment by 1 minvalue 0;
Thanks
First you have to create a procedure which contain the SQL as you mention. Then you have to create a schedule job which will execute the procedure and this job will run once in a year.
CREATE OR REPLACE PROCEDURE RESET_SEQUENCE
IS
v_next_value number;
v_sequence_name varchar2(100):='SEQUENCE01';
begin
execute immediate 'select ' || v_sequence_name || '.nextval from dual' INTO v_next_value;
execute immediate 'alter sequence ' || v_sequence_name || ' increment by -' || v_next_value || ' minvalue 0';
execute immediate 'select ' || v_sequence_name || '.nextval from dual' INTO v_next_value;
execute immediate 'alter sequence ' || v_sequence_name || ' increment by 1 minvalue 0';
END RESET_SEQUENCE;
/
BEGIN
SYS.DBMS_SCHEDULER.CREATE_JOB
(
job_name => 'RESET_SEQ_YEARLY'
,start_date => TO_TIMESTAMP_TZ('2016/01/01 10:20:41.299669 Asia/Dacca','yyyy/mm/dd hh24:mi:ss.ff tzr')
,repeat_interval => 'FREQ=YEARLY;BYMONTH=DEC; BYMONTHDAY=31;BYHOUR=23;BYMINUTE=59;BYSECOND=59'
,end_date => NULL
,job_class => 'DEFAULT_JOB_CLASS'
,job_type => 'PLSQL_BLOCK'
,job_action => 'begin
RESET_SEQUENCE;
end;'
,comments => 'Last day of the year'
);
SYS.DBMS_SCHEDULER.ENABLE
(name => 'RESET_SEQ_YEARLY');
END;
/
You can create a SCHEDULER JOB like this:
BEGIN
DBMS_SCHEDULER.CREATE_JOB
(
job_name => 'RESET_SEQUENCE'
,repeat_interval => 'FREQ=YEARLY;INTERVAL=1;BYMONTH=1;BYMONTHDAY=1;BYHOUR=0;BYMINUTE=0'
,job_class => 'DEFAULT_JOB_CLASS'
,job_type => 'PLSQL_BLOCK'
,job_action => 'BEGIN EXECUTE IMMEDIATE ''ALTER SEQUENCE p_seq_name INCREMENT BY -3465 MINVALUE 0''; END;'
,enabled => TRUE;
);
END;
/
This job will run every year January, 1st after Midnight.
In order to run it on December, 31st use repeat_interval like
FREQ=YEARLY;INTERVAL=1;BYMONTH=12;BYMONTHDAY=31;BYHOUR=23;BYMINUTE=59