Let's say if I have the following:
create table jobs ( staff_id number, job_name varchar2(1000) not null, start_date date not null, end_date date not null );
This is just a table listing the various staff tasks.
Now employees can only do one task at a time, so I am inserting tasks using the following PL / SQL statement. If the found task is found, adding a task is not required (maybe I should report an error here, but for this simplified example, I ignore this):
create or replace procedure add_job ( p_staff_id number, p_job_name varchar2, p_start_date date, p_end_date date ) as begin insert into jobs ( select p_staff_id, p_job_name, p_start_date, p_end_date from dual where not exists ( select 1 from jobs where staff_id = p_staff_id and (end_date > p_start_date) and (start_date < p_end_date) ) ); end;
The problem is that if I add two different tasks to two different sessions and then complete, I can double orders. in the following way:
-- Session 1: add_job(1, 'Help Alice', to_date('2011/08/21 11:00:00', 'YYYY/MM/DD HH24/MI/SS'), to_date('2011/08/21 13:00:00', 'YYYY/MM/DD HH24/MI/SS')); -- Session 2: add_job(1, 'Help Bob', to_date('2011/08/21 12:00:00', 'YYYY/MM/DD HH24/MI/SS'), to_date('2011/08/21 14:00:00', 'YYYY/MM/DD HH24/MI/SS')); -- Session 1: commit; -- Session 2: commit;
Above, staff_id
1 will be booked from 12:00 to 13:00.
It seems like adding to the top of my procedure:
lock table jobs in exclusive mode;
did the trick, I feel like it's a castle too wide. Is there a way to force the oracle to do something more granular. I would prefer not to spoof dbms_lock
if possible. This page , alluding to select ... for update
, would do the trick, but it gave no details.
Is there a way to stop double reservations without completely locking the table or blocking dbms_lock
? (I use Oracle 10g if that matters).