I'm very new to PL/SQL. And I have the following code:
BEGIN
DBMS_SCHEDULER.create_schedule (
schedule_name => 'By_Days_Of_Weak_Schedule',
start_date => SYSTIMESTAMP,
repeat_interval => 'freq=weekly; BYDAY=MON,TUE,WED');
END;
//Schedule created
create or replace
PROCEDURE set_intervals_procedure (
to_task_id in number,
repetitions_count in number)
AS
interval_string VARCHAR2(255);
start_d TIMESTAMP WITH TIME ZONE;
return_date_after TIMESTAMP WITH TIME ZONE;
next_run_date TIMESTAMP WITH TIME ZONE;
BEGIN
Select START_DATE Into start_d From DBA_SCHEDULER_SCHEDULES
WHERE SCHEDULE_NAME = 'BY_DAYS_OF_WEAK_SCHEDULE';
Select REPEAT_INTERVAL Into interval_string From DBA_SCHEDULER_SCHEDULES
WHERE SCHEDULE_NAME = 'BY_DAYS_OF_WEAK_SCHEDULE';
return_date_after := start_d;
FOR i IN 1..repetitions_count LOOP
DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING(
interval_string,
start_d, return_date_after, next_run_date);
return_date_after := next_run_date;
END LOOP;
END set_intervals_procedure;
The problem is that it doesn't compile. It ignores my Select statements, though they are correct. Could someone possibly tell me where I'm mistaken.
Thanks
Related
I wrote the process, and I would like it to be performed only once a month (on the first day of the month). Here is my code, but it is necessary to adjust the job start interval. And I can not understand how to enter the first day of the month. Also I want to do a similar job but to run it only on the 25th of each month. I will be grateful for your help!
begin
dbms_scheduler.create_job (
job_name => 'My_Job',
job_type => 'STORED_PROCEDURE',
job_action => 'Ins_Test2',
start_date => systimestamp,
repeat_interval => 'freq=minutely; interval = 20; byday=MON,TUE,WED,THU,FRI;',
enabled => true,
comments => 'My new job'
);
end;
Set the interval to
repeat_interval => 'FREQ=MONTHLY;BYMONTHDAY=25'
To evaluate the calendar expression, use DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING. Example:
DECLARE
start_date TIMESTAMP WITH time zone;
return_date_after TIMESTAMP WITH time zone;
next_run_date TIMESTAMP WITH time zone;
BEGIN
-- start date of schedule
start_date :=
to_timestamp_tz('CST 12:00 05-MAY-2012','TZR HH24:MI DD-MON-RRRR');
return_date_after := start_date;
FOR i IN 1..5 LOOP
DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING(
'FREQ=MONTHLY;BYMONTHDAY=25',
start_date, return_date_after, next_run_date);
DBMS_OUTPUT.PUT_LINE('next_run_date: ' || next_run_date at time zone 'PST');
return_date_after := next_run_date;
END LOOP;
END;
/
next_run_date: 25-MAY-12 10.00.00.000000000 AM
next_run_date: 25-JUN-12 10.00.00.000000000 AM
next_run_date: 25-JUL-12 10.00.00.000000000 AM
next_run_date: 25-AUG-12 10.00.00.000000000 AM
next_run_date: 25-SEP-12 10.00.00.000000000 AM
Calling the package inside the job gives an Error report -
ORA-06550: line 8, column 5:
PLS-00103: Encountered the symbol "
);
end; : AUXSQLDBIND4: = SqlDevBind1Z_1; : AUXSQLDBIND3: = SqlDevBind1Z_2; : AUXSQLDBIND2: = SqlDevBind1Z_3; : AUXSQLDBIND1: = SqlDevBind "
Help call the packet with the passed variable work_date for a certain calculation for each day of the month.
Thanks in advance for your help!
DBMS_SCHEDULER.create_job (
job_name => 'J_ACCOUNT_TURNOVER_F',
job_type => 'PLSQL_BLOCK',
start_date => SYSTIMESTAMP, enabled => TRUE,
job_action =>
'declare
start_date number;
end_date number;
work_date date;
begin
start_date := to_number(to_char(to_date('2018-01-01', 'yyyy-MM-dd'), 'j'));
end_date := to_number(to_char(to_date('2018-01-31', 'yyyy-MM-dd'), 'j'));
for cur_r in start_date..end_date loop
work_date := to_char(to_date(cur_r, 'j'), 'yyyyMMdd');
dma.fill_account_turnover_f.fill(work_date);
end loop;
end;'
);
end;
Wouldn't it be simpler if you created a stored procedure and called it, instead of embedding that anonymous PL/SQL block into DBMS_SCHEDULER.CREATE_JOB call? Now you have to escape single quotes, i.e. use two consecutive ones every time. Something like this:
begin
DBMS_SCHEDULER.create_job (
job_name => 'J_ACCOUNT_TURNOVER_F',
job_type => 'PLSQL_BLOCK',
start_date => SYSTIMESTAMP, enabled => TRUE,
job_action =>
'declare
start_date number;
end_date number;
work_date date;
begin
start_date := to_number(to_char(to_date(''2018-01-01'', ''yyyy-MM-dd''), ''j''));
end_date := to_number(to_char(to_date(''2018-01-31'', ''yyyy-MM-dd''), ''j''));
for cur_r in start_date..end_date loop
work_date := to_char(to_date(cur_r, ''j''), ''yyyyMMdd'');
dma.fill_account_turnover_f.fill(work_date);
end loop;
end;'
);
end;
/
Maybe you're allergic to stored procedures :) Here is how you can do it without having to escape each individual quote. It is called the "Q Quote syntax".
DBMS_SCHEDULER.create_job (
job_name => 'J_ACCOUNT_TURNOVER_F',
job_type => 'PLSQL_BLOCK',
start_date => SYSTIMESTAMP, enabled => TRUE,
job_action =>
q'!declare
start_date number;
end_date number;
work_date date;
begin
start_date := to_number(to_char(to_date('2018-01-01', 'yyyy-MM-dd'), 'j'));
end_date := to_number(to_char(to_date('2018-01-31', 'yyyy-MM-dd'), 'j'));
for cur_r in start_date..end_date loop
work_date := to_char(to_date(cur_r, 'j'), 'yyyyMMdd');
dma.fill_account_turnover_f.fill(work_date);
end loop;
end;'
);
end;!'
More examples in this question
I want to create a export table job, but I can't understand why its not working.
my table is Department
create table department (id number, name varchar2(200));
I want to export a csv file for per day at 9:00 pm. I need to create it.
I only know:
0. create a directory
create a PROCEDURE
create a DBMS_SCHEDULER.CREATE_PROGRAM
create a DBMS_SCHEDULER.CREATE_SCHEDULE
create a DBMS_SCHEDULER.CREATE_JOB
excute the job
thanks
Yes, you can use DBMS_SCHEDULER by creating in such a way
DECLARE
v_job_name VARCHAR2(32) := 'jb_exp_emp_data';
BEGIN
DBMS_SCHEDULER.CREATE_JOB(job_name => v_job_name,
job_type => 'STORED_PROCEDURE',
job_action => 'exp_emp_data',
start_date => TO_DATE('11-12-2021 21:00:10',
'DD-MM-YYYY HH24:MI:SS'),
repeat_interval => 'FREQ=DAILY; BYHOUR=21;',
auto_drop => false,
comments => 'Exports the content of the department table every day at 9:00PM o''clock ');
DBMS_SCHEDULER.ENABLE(v_job_name);
END;
/
that starts at the time defined by the start_date parameter, then repeats on every upcoming days at 9pm in the future.
I followed the steps below and it was successful ...
Create a directory (path of export file):
CREATE OR REPLACE DIRECTORY CSVDIR AS 'D:\';
Create a procedure:
Create Or Replace Procedure exp_emp_data Is
today varchar2(200);
fileName varchar2(200);
n_file utl_file.file_type;
v_string Varchar2(4000);
Cursor c_emp Is
Select
id, name
From
department;
Begin
select to_char(sysdate,'yyyymmdd','nls_calendar=persian') into today from dual;
fileName := 'empdata' || today || '.csv';
n_file := utl_file.fopen('CSVDIR', fileName, 'w', 4000);
v_string := 'ID, Name';
utl_file.put_line(n_file, v_string);
-- open the cursor and concatenate fields using comma
For cur In c_emp Loop
v_string := cur.id
|| ','
|| cur.name;
-- write each row
utl_file.put_line(n_file, v_string);
End Loop;
-- close the file
utl_file.fclose(n_file);
Exception
When Others Then
-- on error, close the file if open
If utl_file.is_open(n_file) Then
utl_file.fclose(n_file);
End If;
End;
/
-------- Test
Begin
exp_emp_data;
End;
/
Create a program:
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM (
program_name => 'PROG_EXPORT_TABLE',
program_action => 'exp_emp_data',
program_type => 'STORED_PROCEDURE');
END;
/
Create a job:
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'JOB_EXPORT_TABLE',
job_type => 'STORED_PROCEDURE',
job_action => 'PROG_EXPORT_TABLE',
start_date => '16-nov-2021 11:50:00 pm',
repeat_interval => 'FREQ=DAILY;BYHOUR=23;BYMINUTE=59',
enabled => true
);
END;
/
And enabled it:
exec dbms_scheduler.enable('JOB_EXPORT_TABLE');
I have created a package purging inside that created procedure. How to schedule procedure around 2AM CST?
create or replace package body purging as
PROCEDURE del_exp IS
begin
FOR td IN (
SELECT
table_name
FROM
all_tables
where owner = 'ud_oi' and table_name not like 'lgh%'
)
LOOP
EXECUTE IMMEDIATE 'DELETE FROM ' || td.table_name || ' WHERE TRUNC(case_dt) < TRUNC(sysdate - 38)' ;
END LOOP;
end;
END del_exp;
A simple option is to use DBMS_JOB; if your database is recent, DBMS_SCHEDULER is preferred. You'd do it as follows:
DECLARE
X NUMBER;
BEGIN
SYS.DBMS_JOB.SUBMIT (
job => X,
what => 'begin purging.del_exp; end;',
next_date => TO_DATE ('16.06.2020 02:00:00', 'dd/mm/yyyy hh24:mi:ss'),
interval => 'TRUNC (SYSDATE+1) + 2 / 24',
no_parse => FALSE);
SYS.DBMS_OUTPUT.PUT_LINE ('Job Number is: ' || TO_CHAR (x));
COMMIT;
END;
/
A DBMS_SCHEDULER option (which also shows how to run it during working days (at least, working here where I live)):
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'purging',
job_type => 'PLSQL_BLOCK',
job_action => 'begin purging.del_exp; end;',
start_date => TO_TIMESTAMP_TZ ('16.06.2020 02:00 Europe/Zagreb',
'dd.mm.yyyy hh24:mi TZR'),
repeat_interval => 'FREQ=DAILY; BYDAY=MON,TUE,WED,THU,FRI; BYHOUR=2; BYMINUTE=0',
enabled => TRUE,
comments => 'Purge tables');
END;
/
Just to mention: condition you wrote:
table_name not like 'lgh%'
looks suspicious. Table names are - by default - in UPPERCASE. Unless you create tables using mixed (or lower) case, you can do that by enclosing their names into double quotes. I hope you didn't/don't do that. Therefore, you'd rather use
table_name not like 'LGH%'
I have to create a job periodically.
But firstly I have create a simply job to learn how to create jobs in oracle, because is the first time I use a job.
It runs at systimestamp, but the job doesn't execute.
create or replace procedure job_test
is
begin
update table_a set value_user = 'JOB_EXECUTED' where id = 1;
commit;
end;
/
Then the scheduler job
begin
dbms_scheduler.create_job(
job_name => 'test_job_A',
job_type => 'stored_procedure',
job_action => 'job_test',
start_date = SYSTIMESTAMP,
enabled => true
);
end;
/
Then I consult the column value_user and it hasn't been updated.
select * from table_A where id = 1;
Can anyone explain me what I am missing.
create table user_count (
number_of_users NUMBER(4),
time_of_day TIMESTAMP
);
CREATE OR REPLACE PROCEDURE insert_user_count AS
v_user_count NUMBER(4);
BEGIN
SELECT count(*)
INTO v_user_count
FROM v$session
WHERE username IS NOT NULL;
INSERT INTO user_count
VALUES (v_user_count, systimestamp);
commit;
END insert_user_count;
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM (
program_name => 'PROG_INSERT_USER_COUNT',
program_action => 'INSERT_USER_COUNT',
program_type => 'STORED_PROCEDURE');
END;
BEGIN
DBMS_SCHEDULER.CREATE_SCHEDULE (
schedule_name => 'my_weekend_5min_schedule',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=MINUTELY; INTERVAL=5; BYDAY=SAT,SUN',
end_date => SYSTIMESTAMP + INTERVAL '30' day,
comments => 'Every 5 minutes');
END;
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'my_user_count_job',
program_name => 'prog_insert_user_count',
schedule_name => 'my_weekend_5min_schedule');
END;
exec dbms_scheduler.enable('my_user_count_job’)
select * from user_count;
select job_name, status, run_duration, cpu_used
from USER_SCHEDULER_JOB_RUN_DETAILS
where job_name = ‘MY_USER_COUNT_JOB’;
Indeed your case should work but once(provided there already exists a row with id value equals to 1). Suppose you have an insert statement rather than an update, but doesn't repeat to populate the table with new incremented ID values.
For this, important point is to add repeat_interval argument such as below :
begin
dbms_scheduler.create_job(
job_name => 'test_job_A',
job_type => 'stored_procedure',
job_action => 'job_test',
start_date => SYSTIMESTAMP,
enabled => true,
repeat_interval => 'FREQ=MINUTELY;INTERVAL=5',
auto_drop => false,
comments => 'Inserts new records'
);
end;
/
which inserts new records for each five minutes.