How do i dynamically create a job schedule in a trigger? - oracle

I am creating a library system.
When a book is reserved, i want it to automatically change the status back to "Available" in 3 days if the reserved user does not borrow it.
I can create a trigger to fire when the status is changed to "Reserved" but I am lost on creating a job to happen in 3 days and change the status back to "Available"
Any comments, advises and guidance will be greatly appreciated :)

You should first create a procedure to update the column as you want, taking as an input parameter the book id (or whatever else as PK).
In your trigger, call the submit procedure of dbms_scheduler package and define the start date in 3 days time, without redundance, and to run your procedure defined earlier with the :new.bookid as input parameter.
Once the transaction has be commited later on, the job will be submitted. Else, in case of rollback of the transaction the job will be rolled back as well.
Nicolas.

what language are you coding in?
Generally for something like this I write a cron job which would run periodically (once a day before library hours?), do a query to see everything that's been reserved for more than 3 days, and set it back to available.

Related

call back in dbms_scheduler job Oracle

When we start a job via dbms_schedular, it creates a record in *_SCHEDULER_JOBS
Is there a way at the middle or end of a job. I write onto the record
Example:
Job_A spawns Procedure_B
And inside Procedure_B, I can write back to the record in *_scheduler_jobs in Job_A
As procedure_B is looping on a sequence of sub-task e.g. batch_id=1 to 10
and I want to write id=1 and id=10 into the entry for Job_A in *_SCHEDULER_JOBS
-Thanks for all the help.
Question is a bit vague on "I want to write id=1 and id=10 into the entry for Job_A in *_SCHEDULER_JOBS".
From within the procedure, you can use the SYS_CONTEXT('USERENV','BG_JOB_ID') to get the object id of the scheduler job, and look the owner / name up in ALL_OBJECTS. If the job is owned by the same user as the procedure or has been granted appropriate privileges, it can then call DBMS_SCHEDULER.SET_ATTRIBUTE to make changes to the job. Depending what attribute it changes, that will probably only kick in for the next run of the job.
BG_JOB_ID only works if the job is run from the scheduler, and not if someone is doing dbms_scheduler.run_job within their own session. Given multiple sessions could do this concurrently, you probably don't want them all trying to make changes to the job anyway.

A better approach than Oracle trigger

We're supposed to update some columns in a table 'tab1' with some values(which can be picked up from a different table 'tab2'). Now 'tab1' is getting new records inserted almost every few seconds(from MQ by a different system).
We want to design a solution that will update 'tab1' as soon as there is a new record added to 'tab1'. It doesn't have to be done in the same moment as the record is added, but the sooner its updated, the better. We were considering what can be the best way to do it:
1) First we thought of a 'before insert' trigger on tab1, so we can update the record - but that design was vetted out by our Architect, since the organization doesn't allow use of database triggers(don't know why, but that is a restriction, we have been asked to live with)
2) Second we thought, we will create a stored procedure which will perform the updates to records in 'tab1'. This stored procedure will be called within an long-running loop from a shell script. After every iteration there will be a pause of lets say 3 secs and then next loop will kick off, which will again call the stored proc. So this job will run 12 AM to 11:59 PM and then restarted every night.
My question is - is there a database only solution to this? Any other solutions are also welcome, but simplicity of design will be a huge plus. One colleague was wondering if there is a 'trigger-like' solution, which will perform the job within the database itself - so we don't have to write a shell script.
Any pointers will be appreciated!
Triggers The obvious solution.
DBMS_SCHEDULER Another obvious solution.
Continuous Query Notification This would be a "trigger-like" solution. It's meant to call an application when the results of a specific query would be different. But you can call PL/SQL instead of an application, and the query could be a simple select * from tab1; which would fire on any table changes. Normally I'd hope an architect would be to look at this solution and say, "a trigger would be a lot simpler".
DBMS_JOBS This is the old version of DBMS_SCHEDULER and is not as good. But it's different and maybe it won't be caught as an unauthorized feature.
Ignore the Architect The problem isn't that he disapproved of using triggers or jobs; there may be legitimate reasons to ban those technologies. The problem is that he rejected a sound idea without clearly articulating why it wasn't allowed. If he understood databases, or cared about your project, or acted like a professional, he would have said something like, "Oh, I'm sorry, I know that's the typical way to do this, but we don't allow it because of X, Y, Z."
To answer your questions:
Q: Is there a database only solution to this?
Unlikely, given all the limitations on your architecture.
Q: Any other solutions are also welcomed
It seems your likely solution is to have your application handle what would normally be handled by a trigger or stored procedure. Just do it all in one transaction.

Quartz schedular: how do I setup dynamic job arguments

I'm setting up a Quartz driven job in a Spring. The job needs a single argument which is the id of a database record that it can use to locate the data it needs to process.
The sequence is:
Job starts,
locates next available record id,
processes data.
Because the record id is unknown until the job starts, I cannot set it up when I create the job. I also need to account for restarts if things go bad. From reading Quartz doco it appears that if I store the record Id in the trigger's JobDataMap, then when the server restarts, the job will automatically restart with the same record Id it was original started with.
This is where things get tricky, I'm trying to figure out where and when to get the record Id so I can store it in the trigger's JobDataMap. I'm thinking I need to implement a TriggerListener and use it to set the record Id in the JobDataMap when the triggerFired() callback is called. This will involve a call to the database to get the record Id.
I'm not really sure if this approach is the correct one, or whether I'm barking up the wrong tree. Can someone with some quartz experience tell me if this is correct, or if there is a better way to configure a jobs arguments so that they can be dynamically set and a restart will preserve them?
Thanks
Derek

DBMS_JOB usage: 'Singular' job keeps recurring every five seconds

I learned (the hard way) that DDL statements cannot be executed in the non-transactional context of a logon trigger, and that the solution is a job. I want the job to be executed immediately and one single time and therefore set the next_date parameter to sysdate and the interval parameter to null.
Here is what I execute in the trigger:
dbms_job.submit(
job=>jobNumber,
what=>'someProcedure(someParameter);',
next_date=>sysdate,
interval=>null
);
This works quite good, but once the trigger has been fired (and the above command has been submitted) for the time, the audit log shows that the job keeps reappearing exactly every five seconds under the same user account it has been submitted under for the first time. The associated program is always something like ORACLE.EXE (J001), although it was of course a user session initiated from a client application.
Can anyone explain this to me please? I hoped to get a singular execution of the job and not an eternal recurrence. Thanks in advance!

How should I implement a database cron job logger?

I use PHP and Oracle, with crontab executing the PHP scripts at scheduled times. My current logging/auditing solution involves simple log files. I'd like to save my cron execution logs to a database instead.
Right now I'm trying to design the process so that when a cron job starts I create a record in an CronExecution table. Then every time I want to log something for that cron I'll put a record in a CronEvent table which will have a foreign key to the CronExecution table.
I plan to log all events using a PRAGMA AUTONOMOUS pl/sql procedure. With this procedure I will be able to log events inside of other pl/sql procedures and also from my PHP code in a consistent manner.
To make it more robust, my plan is to have a fallback to log errors to a file in the event that the database log calls fail.
Has anybody else written something similar? What suggestions do you have based on your experience?
Yep, I've done this several times.
The CronExecution table is a good idea. However, I don't know that you really need to create the CronEvent table. Instead, just give yourself a "status" column and update that column.
You'll find that makes failing over to file much easier. As you build lots of these CronExecutions, you'll probably have less interest in CronEvents and more interest in the full status of the execution.
Wrap all of the update calls in stored procedures. You definitely have that correct.
Including a 'schedule' in your CronExecution will prove handy. It's very easy to have a lot of cron jobs and not be able to connect the dots on "how long did this take?" and "when is this supposed to run". Including a "next scheduled run" on completion of a job will make your life much easier.
You will want to read the documentation on DBMS_SCHEDULER.
It's a little bit of work to implement (what isn't?), but it will allow you to control scheduled and one-time jobs from within the database. That includes OS-level jobs.

Resources