Reputation: 47
I have the following problem: I have a database of a Hotel, and I have to handle collisions while booking rooms.
So let's say, Quest1 wants to book room2 between 2016-11-10 and 2016-11-15, but this room has been booked by Quest3 between 2016-11-07 and 2016-11-14 (You can book the room FROM the day people leave), and my function should be called in a constraint to tell he cant book it for those dates.
I have an EMPTY table for bookings. The problem is, that when using the function in a query, it returns that room2 was booked 0 times between 2016-11-10 and 2016-11-15 (since the table is empty. even if its not empty, it will return the right value too, tested it.), but while using it as a constraint, it comes up as the row was not updated, the insert statement is conflicted with my constraint.
The function:
ALTER FUNCTION [dbo].[Booked]
(
@room int,
@from date,
@to date
)
RETURNS int
AS
BEGIN
return(
SELECT count(*)
FROM BOOKINGS
WHERE room = @room AND NOT (@from >= to OR @to < from)
)
END
Constraint:
ALTER TABLE BOOKINGS ADD
CONSTRAINT chk_isBooked
CHECK ([dbo].Booked([room], [from],[to])=(0))
Thanks in advance!
Upvotes: 2
Views: 62
Reputation: 16146
The following script does work. It appears that when the CHECK constraint is fired, the row is already in the table and is being counted in the function. I added an indentity to the bookings table to avoid that.
CREATE TABLE dbo.bookings(
id int identity(1,1),
room int ,
[from] date,
[to] date
);
GO
CREATE FUNCTION dbo.IsBooked(@id int,@room int, @from date, @to date)
RETURNS BIT
AS
BEGIN
RETURN CASE WHEN EXISTS(SELECT * FROM bookings WHERE id<>@id AND room=@room AND NOT(@from>=[to] OR @to<[from])) THEN 1 ELSE 0 END
END
GO
ALTER TABLE dbo.bookings ADD CONSTRAINT chk_isbooked CHECK (dbo.IsBooked(id,room,[from],[to])=0);
GO
INSERT INTO dbo.bookings(room,[from],[to])VALUES(1,'20160101','20160107'); -- success
INSERT INTO dbo.bookings(room,[from],[to])VALUES(1,'20160101','20160107'); -- fail
Upvotes: 1