我有以下问题:我有一个酒店的数据库,我必须在预订房间时处理碰撞。
所以,让我们说,Quest1想要在2016-11-10和2016-11-15之间预订room2,但这个房间已经被Quest3在2016-11-07和2016-11-14之间预订(你可以预订房间从人们离开的那一天开始,我的功能应该在约束中调用,告诉他不能在那些日期预订它。
我有预订的EMPTY表。问题是,当在查询中使用该函数时,它返回room2在2016-11-10和2016-11-15之间被预订0次(因为该表是空的。即使它不为空,它将返回正确的值,测试它。),但是当使用它作为约束时,它会在行未更新时出现,insert语句与我的约束冲突。
功能:
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
约束:
ALTER TABLE BOOKINGS ADD
CONSTRAINT chk_isBooked
CHECK ([dbo].Booked([room], [from],[to])=(0))
提前致谢!
答案 0 :(得分:1)
以下脚本确实有效。看起来当触发CHECK约束时,该行已经在表中并且正在函数中计数。为了避免这种情况,我在预订表中添加了一个缩进词。
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