How to implement timer for heartbeat - oracle

I need to implement a heartbeat function written in PL/SQL, to ping a web service every 5 minutes. I know that PL/SQL is really not the correct language to be writing this in, but it has to be done this way.
DECLARE
stored_time TIMESTAMP
curr_time TIMESTAMP
BEGIN
stored_time := current_timestamp;
WHILE (curr_time - stored_time > 5)
pulse_heartbeat();
stored_time := current_timestamp;
END WHILE
The pseudo code above is really the only way i think it could be done. I know there is a timer package with oracle, but i'm not sure if i should use it or not. Any ideas?

It seems like you want to schedule the procedure execution every 5 minutes. I suggest use DBMS_SCHEDULER.
Database level
BEGIN
DBMS_SCHEDULER.create_job (
job_name => 'pulse_heartbeat',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN pulse_heartbeat; END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'freq=minutely; interval=5; bysecond=0;',
enabled => TRUE);
END;
/
Above uses calendaring syntax to repeat interval every 5 minutes. It creates a job at database level.
OS level
You could also schedule scripts to run at OS level. For example, in UNIX based platforms, you could create a shell script and schedule as cron job.

Related

How to schedule one time executable job in Oracle?

I want to schedule a job that will execute only once; example on 01/01/2023 00:00:00. It should not repeat again. This job will call a program with a stored procedure that will update some tables.
I have written the below code by referring the answers of this question. It is not working when I set the end_date as the same date with different time. Is repeat_interval mandatory?
-- Procedure
CREATE OR REPLACE PROCEDURE P_INSURANCE_DEACTIVATION
IS
BEGIN
UPDATE SCHEME SET SCC_STATUS = 'N', US_CODE = 'D001' WHERE SC_CODE = 'N013';
UPDATE INSURANCE SET INC_STATUS = 'N', US_CODE = 'D001' WHERE IN_CODE = 'N007';
COMMIT;
END;
-- Schedule
BEGIN
DBMS_SCHEDULER.CREATE_SCHEDULE (
schedule_name => 'SCH_INSURANCE_DEACT',
start_date => TO_DATE('22-12-2022 18:05:00','DD-MM-YYYY HH24:MI:SS'),
repeat_interval => 'FREQ=MINUTELY; INTERVAL=1; ',
end_date => TO_DATE('22-12-2022 18:07:00','DD-MM-YYYY HH24:MI:SS'),
comments => 'Only once');
END;
-- Scheduled Program
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM (
program_name => 'PROG_INSURANCE_DEACT',
program_action => 'P_INSURANCE_DEACTIVATION',
program_type => 'STORED_PROCEDURE');
END;
-- Scheduled Job
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'JOB_INSURANCE_DEACT',
program_name => 'PROG_INSURANCE_DEACT',
schedule_name => 'SCH_INSURANCE_DEACT');
END;
exec dbms_scheduler.enable('JOB_INSURANCE_DEACT’)
After looking at the documentation for DBMS_SCHEDULER, you can see that you can create a scheduled job without needing to define a schedule as long as you set a start time.
Personally, I wouldn't bother creating a procedure and program since the code being executed is so simple and it is just a one-time job.
The code below can be used to create a job that will run at midnight on Jan 1st 2023, but you might need to adjust the time zone for your scenario since midnight is at a different time depending which time zone you are in.
BEGIN
DBMS_SCHEDULER.create_job (job_name => 'JOB_INSURANCE_DEACT',
job_type => 'PLSQL_BLOCK',
job_action => q'[BEGIN
UPDATE SCHEME SET SCC_STATUS = 'N', US_CODE = 'D001' WHERE SC_CODE = 'N013';
UPDATE INSURANCE SET INC_STATUS = 'N', US_CODE = 'D001' WHERE IN_CODE = 'N007';
COMMIT;
END;]',
start_date => TIMESTAMP '2023-01-01 00:00:00 -05:00',
enabled => TRUE);
END;
As an additional note, you do not need to have a COMMIT at the end of your code being executed by a job. When a job completes, it will automatically commit.

I am attempting to update the apex calendar automatically every minute using a procedure

This code is a procedure to update the task every time a work shift as pass is scheduled and move it to another work shift and only ends when the task is closed. The scheduled for the work shift work this way:
1º: 7:00 to 15:00
2º: 15:00 to 23:00
3º: 23:00 to 7:00
But the problem I am having it this code is the part of DBMS_SCHEDULER, I am attempting to update the Apex calendar so it updates every minute but only updates when I run the first time, but when I attempt to run a second time, it gives this error:
ORA-27477: "GERAL.TURNOS8" already exists
create or replace PROCEDURE
check_task_turnos AS
CURSOR c_turnos
IS
SELECT TIPO,ID,estado,calendar_start,calendar_end
,Case
WHEN to_number(to_char(calendar_start,'HH24')) >= 7 AND to_number(to_char(calendar_end,'HH24')) < 15
THEN 'apex-cal-yellow'
when to_number(to_char(calendar_start,'HH24')) >= 15 AND to_number(to_char(calendar_end,'HH24')) < 23
THEN 'apex-cal-yellow'
when (to_number(to_char(calendar_start,'HH24')) >= 23 AND to_number(to_char(calendar_end,'HH24')) < 24
OR
to_number(to_char(calendar_start,'HH24')) >= 0 AND to_number(to_char(calendar_end,'HH24')) <= 7)
THEN 'apex-cal-yellow'
else null
end
FROM NVG_PASSAGEMTURNO
WHERE TIPO='To Do'
AND estado='Aceite';
BEGIN
FOR i IN c_turnos
LOOP
-- This table is for register reference that the task as changed the star time and end time
INSERT INTO NVG_REGISTAR_PASSAGEM(passagem_id,
start_date,
end_date
)
VALUES(i.id ,
i.calendar_start+(8/24) ,
i.calendar_end+(8/24));
-- update of start time and end time for updating the apex calendar
UPDATE NVG_PASSAGEMTURNO
SET calendar_start = i.calendar_start+(8/24)
, calendar_end = i.calendar_end+(8/24)
WHERE ID = i.ID;
END LOOP;
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'turnos8',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN
PKG_TURNOS.check_task_turnos;
END;',
number_of_arguments => 0,
start_date => TO_TIMESTAMP_TZ('2018-11-08 12:44:10.000000000 EUROPE/LONDON','YYYY-MM-DD HH24:MI:SS.FF TZR'),
repeat_interval => 'FREQ=MINUTELY; INTERVAL=1',
end_date => NULL,
enabled => TRUE,
auto_drop => FALSE,
comments => '');
END;
end;
It doesn't make sense to create a job every time you run that PL/SQL piece of code. This is what you're currently trying to do:
procedure > creates a job > calls the same procedure > creates the same job > calls the same procedure > creates the same job ...
You should:
create the procedure (check_task_turnos)
don't create a job within!
separately, create a job and schedule it to run every minute
it will call the check_task_turnos procedure, but it won't be creating the job all over again (besides, as you saw, it just won't work)

what if there is no repeat_interval in dbms_scheduler.create_job

I have created a Job using this.
BEGIN
dbms_scheduler.create_job (
job_name => 'test_JOB',
job_type => 'PLSQL_BLOCK',
JOB_ACTION => 'UP_TRYNR;',
start_date =>sysdate,
enabled => true,
repeat_interval => 'FREQ=DAILY;INTERVAL=1'
);
END;
If I create the job without specifying repeat_interval what will happen? i.e.
BEGIN
dbms_scheduler.create_job (
job_name => 'test_JOB',
job_type => 'PLSQL_BLOCK',
JOB_ACTION => 'UP_TRYNR;',
start_date =>sysdate,
enabled => true,
);
END;
Any suggestion will be helpful. Thanks.
The DBMS_SCHEDULER package includes functionality that can be used to set up and manage the timetabling and execution of tasks that need to be run according to a – repeating or non-repeating – schedule.
DBMS_SCHEDULER breaks the process of scheduling a task into 3 parts:
Create a schedule
Identify a ‘program’ – by which they mean the procedure you wish to
run
Create a ‘job’ – by which they mean chain a program to a schedule.
As name suggests Repeat_interval,describes the frequency when the programs needs to be executed. This is a bit like the cron syntax in UNix.
If you create it without any Repeat_interval,it would execute only once at the specified startdate and then remain dormant.

Run the same Procedure at the same time in Oracle?

I'm currently using:
BEGIN
PACKAGE1.PROCEDURE1('PARAM_1','PARAM_A','PARAM_B');
END;
I need to run the same procedure multiple times (Oracle), but this time changing only the first parameter, for example:
PACKAGE1.PROCEDURE1('PARAM_2','PARAM_A','PARAM_B');
PACKAGE1.PROCEDURE1('PARAM_3','PARAM_A','PARAM_B');
How can i accomplish this? Thank you in advance.
In anonym plsql block write a loop with number of iteration depends on how many parameters You want to call procedure with. At the top of loop put logic that will be setting a paramter an then call a procedure with it. But remember that there is no option in plsql to read data from console or user during a program run.
// I think that You can ask about passing an other variable in loop each time, I am not sure is it can be done in plsql You can try use
execute_immidiate
command with string conncatenate as a parameter name.
You Package Procedure must be with IN OUT parameter and i assume the first parameter is IN so the master should take care of the thing of supplying the values to this.
Procedure is working as expected now the external stream of incoming this have to take which is coming from outer source or some other passing mechanism.
Just align those to this package procedure and you may call this procedure as many time as you want according to IN this takes.
You could try to submit it as job if you want to run the same procedure simultaneously.
BEGIN
begin
dbms_scheduler.create_job
(
job_name => 'One_Time_Job_1',
job_type => 'PLSQL_BLOCK',
job_action => 'begin PACKAGE1.PROCEDURE1('PARAM_2','PARAM_A','PARAM_B'); end;',
start_date => sysdate,
enabled => TRUE,
auto_drop => TRUE,
comments => 'one-time job');
end;
begin
dbms_scheduler.create_job
(
job_name => 'One_Time_Job_2',
job_type => 'PLSQL_BLOCK',
job_action => 'begin PACKAGE1.PROCEDURE1('PARAM_3','PARAM_A','PARAM_B'); end;',
start_date => sysdate,
enabled => TRUE,
auto_drop => TRUE,
comments => 'one-time job');
end;
END;
look at DBMS_SCHEDULER for further details.
If this is for an ongoing production process with a fixed number of parallel procedures, I would consider using a Scheduler Chain.
This would execute all the procedures at the same time, and give you extra features, such as:
the ability to run other procedures when one or all of them has completed
control over which procedures run afterwards, depending on the success or failure of the procedures.

DBMS SCHEDULER Job with input

Hi I have a stored procedure in oracle that I would like to run periodically. Firstly I got my DBMS_SCHEDULER Job to compile (see below) and I can even see the job be created and drop it though I don't see the result of the stored procedure occur in the table it is supposed to effect and the stored procedure has been tested.
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'JOB_QUERY',
job_type => 'PLSQL_BLOCK', -- see oracle documentation on types --
job_action => 'BEGIN RUNREPORT(''NAME'', ''VERSION'', ''04-Jun-13'', ''11-Jun-13''); END;',
start_date => to_date('2013-08-19 16:35:00', 'YYYY-MM-DD HH24:MI:SS' ),
repeat_interval => 'FREQ=MINUTELY;BYMINUTE=10', -- every 10 minutes.
end_date => NULL,
enabled => TRUE,
comments => 'Daily Jira Query Update');
END;
I was attempting to simply make it run every ten minutes though I see no changes. Also I wanted to be able to pass SYSDATE or the current date to the procedure in the dbms_scheduler job but I cant get it to work with the apostrophes.
Thanks
You have to COMMIT your DML statements. There is no COMMIT in PL/SQL block and I guess in procedure RUNREPORT either.
You don't need an apostrophe around sysdate, it's not a string literal.
job_action => 'BEGIN RUNREPORT(''NAME'', ''VERSION'', sysdate, ''11-Jun-13''); COMMIT; END;',
BYMINUTE does not mean what you would expect. From documentation:
"This specifies the minute on which the job is to run. Valid values are 0 to 59. As an example, 45 means 45 minutes past the chosen hour". What you need is
repeat_interval => 'FREQ=MINUTELY;INTERVAL=10'
You can check next run date and more by querying user_scheduler_jobs.
If you are calling the stored procedure from DMBS Scheduled job you can try below.
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
JOB_NAME => 'SCHEMA.MY_DBMS_SCHEDULED_JOB',
JOB_TYPE => 'STORED_PROCEDURE',
JOB_ACTION => 'SCHEMA.STORED_PROCEDURE_TO_BE_CALLED',
START_DATE => '01-AUG-13 12.00.00 AM',
REPEAT_INTERVAL => 'FREQ=DAILY;BYHOUR=0;BYMINUTE=10',
AUTO_DROP => FALSE,
ENABLED => TRUE,
NUMBER_OF_ARGUMENTS => 0,
COMMENTS => 'Scheduled job to perform updates.');
END;
/
To see if your scheduler log you can use below query.
SELECT * FROM all_SCHEDULER_JOB_LOG
where job_name='MY_DBMS_SCHEDULED_JOB'
order by log_id desc;

Resources