Home » SQL & PL/SQL » SQL & PL/SQL » Check Time In Query (Oralce 10g)
Check Time In Query [message #630660] Fri, 02 January 2015 04:10 Go to next message
mamalik
Messages: 268
Registered: November 2008
Location: Pakistan
Senior Member

Dear All,
I have following table for booking of vehicles.
create table vehicle_booking (vehicle_number number,booked_from date,booked_too date)

SET DEFINE OFF;
Insert into VEHICLE_BOOKING
   (VEHICLE_NUMBER, BOOKED_FROM, BOOKED_TOO)
 Values
   (1, TO_DATE('12/01/2014 11:30:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('12/01/2014 21:30:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into VEHICLE_BOOKING
   (VEHICLE_NUMBER, BOOKED_FROM, BOOKED_TOO)
 Values
   (1, TO_DATE('01/01/2015 13:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('01/01/2015 15:30:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into VEHICLE_BOOKING
   (VEHICLE_NUMBER, BOOKED_FROM, BOOKED_TOO)
 Values
   (1, TO_DATE('01/01/2015 12:30:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('01/01/2015 13:30:00', 'MM/DD/YYYY HH24:MI:SS'));

Now I have following data.
Select * from Vehicle_Booking
VEHICLE_NUMBER	BOOKED_FROM	BOOKED_TOO

1	12/1/2014 11:30:00 AM	12/1/2014 9:30:00 PM
1	1/1/2015 1:00:00 PM	1/1/2015 3:30:00 PM
1	1/1/2015 12:30:00 PM	1/1/2015 1:30:00 PM


In above data please note that in third row i have booked vehicle number 1 from time 12:30 to 1:30 Pm but same vehicle is booked from 1:00 Pm To 3:30 Pm in second record, Third record must not be created because this time is between above time in second row.

Please suggest how can i check before inserting new record that the vehicle is already booked in between time or for time which is going to be booked.

Thanks in Advance.

Best Regards,
Asif.
Re: Check Time In Query [message #630661 is a reply to message #630660] Fri, 02 January 2015 05:10 Go to previous messageGo to next message
Littlefoot
Messages: 21808
Registered: June 2005
Location: Croatia, Europe
Senior Member
Account Moderator
For a new record, FROM TIME must be > MAX(TO TIME) of previously entered records.
Re: Check Time In Query [message #630662 is a reply to message #630660] Fri, 02 January 2015 05:17 Go to previous messageGo to next message
Lalit Kumar B
Messages: 3174
Registered: May 2013
Location: World Wide on the Web
Senior Member
Edit : Please discard.

The trigger approach doesn't seem to work for concurrent sessions.

[Updated on: Fri, 02 January 2015 05:25]

Report message to a moderator

Re: Check Time In Query [message #630663 is a reply to message #630662] Fri, 02 January 2015 05:22 Go to previous messageGo to next message
cookiemonster
Messages: 13920
Registered: September 2008
Location: Rainy Manchester
Senior Member
That trigger will throw a mutating table error if you ever do an insert select.
Re: Check Time In Query [message #630664 is a reply to message #630663] Fri, 02 January 2015 05:30 Go to previous messageGo to next message
Lalit Kumar B
Messages: 3174
Registered: May 2013
Location: World Wide on the Web
Senior Member
cookiemonster wrote on Fri, 02 January 2015 16:52
That trigger will throw a mutating table error if you ever do an insert select.


Yes, agreed. And not only that, the trigger won't work for concurrent sessions. It will allow the record if the other session is not yet committed. And after committing both the sessions, all the records would already be inserted.

Sorry, it was a bad idea.
Re: Check Time In Query [message #630666 is a reply to message #630664] Fri, 02 January 2015 05:34 Go to previous messageGo to next message
Lalit Kumar B
Messages: 3174
Registered: May 2013
Location: World Wide on the Web
Senior Member
Perhaps this AskTom link is useful https://asktom.oracle.com/pls/asktom/f?p=100:11:0%3a%3a%3a%3aP11_QUESTION_ID:474221407101
Re: Check Time In Query [message #630667 is a reply to message #630664] Fri, 02 January 2015 05:36 Go to previous messageGo to next message
Littlefoot
Messages: 21808
Registered: June 2005
Location: Croatia, Europe
Senior Member
Account Moderator
I'd rather you kept your original message as it was (trigger? What trigger? I don't see any). Removing its contents is confusing. Editing is restricted for a reason; you shouldn't abuse your moderator privileges to circumvent it.
Re: Check Time In Query [message #630668 is a reply to message #630667] Fri, 02 January 2015 05:55 Go to previous messageGo to next message
Lalit Kumar B
Messages: 3174
Registered: May 2013
Location: World Wide on the Web
Senior Member
Littlefoot wrote on Fri, 02 January 2015 17:06
you shouldn't abuse your moderator privileges to circumvent it.


You have certainly mistaken. I didn't use any moderator privilege to edit, I was on the same page and edited normally. I submitted my answer at Fri, 02 January 2015 16:47 and I didn't refresh the page, and then simply used Edit and edit was made at Fri, 02 January 2015 16:55.

No issues, I am re-posting the trigger approach. Here it is -

SQL> ALTER SESSION SET NLS_DATE_FORMAT='MM/DD/YYYY HH24:MI:SS';

Session altered.

SQL>
SQL> DROP TABLE vehicle_booking;

Table dropped.

SQL>
SQL> CREATE TABLE vehicle_booking (vehicle_number NUMBER,booked_from DATE,booked_too DATE);

Table created.

SQL>
SQL> SET DEFINE OFF;
SQL> CREATE OR REPLACE TRIGGER trg_book_time BEFORE
  2    INSERT ON vehicle_booking FOR EACH ROW WHEN (new.booked_from IS NOT NULL) DECLARE cnt NUMBER;
  3    BEGIN
  4      SELECT COUNT(*)
  5      INTO cnt
  6      FROM vehicle_booking
  7      WHERE (:NEW.booked_from BETWEEN BOOKED_FROM AND BOOKED_TOO
  8      OR :new.booked_too BETWEEN BOOKED_FROM AND BOOKED_TOO);
  9      IF ( cnt > 0 ) THEN
 10        raise_application_error(-20000,'Overlapping date ranges');
 11      END IF;
 12    END;
 13    /

Trigger created.

SQL>
SQL> show errors
No errors.
SQL>
SQL> Insert into VEHICLE_BOOKING
  2     (VEHICLE_NUMBER, BOOKED_FROM, BOOKED_TOO)
  3   Values
  4     (1, TO_DATE('12/01/2014 11:30:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('12/01/2014 21:30:00', 'MM/DD/YYYY HH24:MI:SS'));

1 row created.

SQL> Insert into VEHICLE_BOOKING
  2     (VEHICLE_NUMBER, BOOKED_FROM, BOOKED_TOO)
  3   Values
  4     (1, TO_DATE('01/01/2015 13:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('01/01/2015 15:30:00', 'MM/DD/YYYY HH24:MI:SS'));

1 row created.

SQL> Insert into VEHICLE_BOOKING
  2     (VEHICLE_NUMBER, BOOKED_FROM, BOOKED_TOO)
  3   VALUES
  4     (1, TO_DATE('01/01/2015 12:30:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('01/01/2015 13:30:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into VEHICLE_BOOKING
            *
ERROR at line 1:
ORA-20000: Overlapping date ranges
ORA-06512: at "LALIT.TRG_BOOK_TIME", line 9
ORA-04088: error during execution of trigger 'LALIT.TRG_BOOK_TIME'


SQL>
SQL>
SQL> SELECT * FROM vehicle_booking;

VEHICLE_NUMBER BOOKED_FROM         BOOKED_TOO
-------------- ------------------- -------------------
             1 12/01/2014 11:30:00 12/01/2014 21:30:00
             1 01/01/2015 13:00:00 01/01/2015 15:30:00

SQL>
Re: Check Time In Query [message #630669 is a reply to message #630668] Fri, 02 January 2015 06:11 Go to previous messageGo to next message
Littlefoot
Messages: 21808
Registered: June 2005
Location: Croatia, Europe
Senior Member
Account Moderator
Well, you posted it (all times are CET) at 12:17. Cookiemonster read your message and replied at 12:22. Finally, you edited it at 12:25. That's all I can see.

Anyway, thank you for reposting its contents.
Re: Check Time In Query [message #630670 is a reply to message #630669] Fri, 02 January 2015 06:27 Go to previous messageGo to next message
Lalit Kumar B
Messages: 3174
Registered: May 2013
Location: World Wide on the Web
Senior Member
Littlefoot wrote on Fri, 02 January 2015 17:41
That's all I can see.


I understand. But if we press EDIT before someone else has replied, edit our post, take a while to think and apply all changes, it seems like the edit was done later(meanwhile someone might have posted a reply). I had similar confusion when I tested long ago here. Anyway, sorry for the confusion Sad
Re: Check Time In Query [message #630671 is a reply to message #630670] Fri, 02 January 2015 07:04 Go to previous messageGo to next message
John Watson
Messages: 8931
Registered: January 2010
Location: Global Village
Senior Member
Apart from all that, what about a solution? I thought the Rules Manager might do it (example here, http://www.orafaq.com/node/2449) but as it doesn't exist in 12.x perhaps one shouldn't suggest it.

I think a variation on te trigger approach could work. Consider this:
create global temporary table vb_tmp as select * from VEHICLE_BOOKING;

CREATE OR REPLACE TRIGGER trg_book_time BEFORE
    INSERT ON vb_tmp FOR EACH ROW WHEN (new.booked_from IS NOT NULL) DECLARE cnt NUMBER;
    BEGIN
      SELECT COUNT(*)
      INTO cnt
      FROM vehicle_booking
      WHERE (:NEW.booked_from BETWEEN BOOKED_FROM AND BOOKED_TOO
      OR :new.booked_too BETWEEN BOOKED_FROM AND BOOKED_TOO);
      IF ( cnt > 0 ) THEN
        raise_application_error(-20000,'Overlapping date ranges');
      END IF;
      insert into VEHICLE_BOOKING values (:new.vehicle_number,:new.booked_from,:new.booked_too);
    END;
    /
and now do all the inserts into vb_tmp. That solve's CM's issue of INSERT...SELECT throwing a mutating table error. To avoid LK's issue with concurrency one could lock the parent row in VEHICLE (assuming that the application does have such a table, and that VEHICLE_BOOKING has an appropriate foreign key constraint) to serialize bookings for the same car.
It is all very awkward, though. Isn't there a better way?


--update: corrected the trigger code, it had a change I was using for testing.

[Updated on: Fri, 02 January 2015 07:05]

Report message to a moderator

Re: Check Time In Query [message #630672 is a reply to message #630671] Fri, 02 January 2015 08:00 Go to previous messageGo to next message
Lalit Kumar B
Messages: 3174
Registered: May 2013
Location: World Wide on the Web
Senior Member
I think in the trigger approach, we should also add the filter on vehicle_number. User should be allowed to book a vehicle having different vehicle_number if not overlapping the interval.
Re: Check Time In Query [message #630675 is a reply to message #630671] Fri, 02 January 2015 09:22 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
And how does it solve multi-session issue? You still have to serialize somewhere. One possible solution is based on booking rules. For example, I'll assume book from/to time is on quarter-hour:

create table vehicle_booking(
                             vehicle_number number,
                             booked_from date,
                             booked_to date
                            )
/
create table vehicle_booking_detail(
                                    vehicle_number number,
                                    booked_dt date
                                   )
/
alter table vehicle_booking_detail
  add constraint vehicle_booking_detail_pk
    primary key(vehicle_number,booked_dt)
/
create or replace
  trigger prevent_double_booking
    before insert
    on vehicle_booking
    for each row
    begin
        insert
          into vehicle_booking_detail
          select  :new.vehicle_number,
                  :new.booked_from + (level - 1) / 96
            from  dual
            connect by :new.booked_from + (level - 1) / 96 <= :new.booked_to;
end;
/


Single session:

SQL> Insert into VEHICLE_BOOKING
  2   Values
  3     (1, TO_DATE('12/01/2014 11:30:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('12/01/2014 21:30:00', 
'MM/DD/YYYY HH24:MI:SS'));

1 row created.

SQL> Insert into VEHICLE_BOOKING
  2   Values
  3     (1, TO_DATE('01/01/2015 13:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('01/01/2015 15:30:00', 
'MM/DD/YYYY HH24:MI:SS'));

1 row created.

SQL> Insert into VEHICLE_BOOKING
  2   Values
  3     (1, TO_DATE('01/01/2015 12:30:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('01/01/2015 13:30:00', 
'MM/DD/YYYY HH24:MI:SS'));
Insert into VEHICLE_BOOKING
            *
ERROR at line 1:
ORA-00001: unique constraint (SCOTT.VEHICLE_BOOKING_DETAIL_PK) violated
ORA-06512: at "SCOTT.PREVENT_DOUBLE_BOOKING", line 2
ORA-04088: error during execution of trigger 'SCOTT.PREVENT_DOUBLE_BOOKING'


SQL> 


Multi-session:

SQL> -- Session 1
SQL> Insert into VEHICLE_BOOKING
  2   Values
  3     (1, TO_DATE('12/01/2014 11:30:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('12/01/2014 21:30:00', 
'MM/DD/YYYY HH24:MI:SS'));

1 row created.

SQL> Insert into VEHICLE_BOOKING
  2   Values
  3     (1, TO_DATE('01/01/2015 13:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('01/01/2015 15:30:00', 
'MM/DD/YYYY HH24:MI:SS'));

1 row created.

SQL>


Session 1 didn't commit yet while session 2 issues:

SQL> --Session 2
SQL> Insert into VEHICLE_BOOKING
  2   Values
  3     (1, TO_DATE('01/01/2015 12:30:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('01/01/2015 13:30:00', 
'MM/DD/YYYY HH24:MI:SS'));


At this point session 2 waits since it is trying inserting vehicle_booking_detail row(s) with same PK value.

Now session 1 commits:

SQL> commit;

Commit complete.

SQL> 


This releases locks and session 2 fails with:

Insert into VEHICLE_BOOKING
*
ERROR at line 1:
ORA-00001: unique constraint (SCOTT.VEHICLE_BOOKING_DETAIL_PK) violated
ORA-06512: at "SCOTT.PREVENT_DOUBLE_BOOKING", line 2
ORA-04088: error during execution of trigger 'SCOTT.PREVENT_DOUBLE_BOOKING'


SQL> 


SY.
Re: Check Time In Query [message #630715 is a reply to message #630675] Sat, 03 January 2015 09:45 Go to previous message
Kevin Meade
Messages: 2103
Registered: December 1999
Location: Connecticut USA
Senior Member
Here is another good one from Tom. It gets pretty deep, especially when talking about using different concurrency models (whooooo!), but it is the kind of stuff people need to read more.

Of particular note is the idea that you need to serialize your transaction at some point in order to prevent transaction anomalies.

Good luck. Kevin
Previous Topic: Dynamic monthly sales report
Next Topic: Text based search
Goto Forum:
  


Current Time: Thu Apr 25 01:43:09 CDT 2024