函数在查询中有效但不在约束中

时间:2016-11-09 17:31:55

标签: sql-server tsql

我有以下问题:我有一个酒店的数据库,我必须在预订房间时处理碰撞。

所以,让我们说,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)) 

提前致谢!

1 个答案:

答案 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