我有一个代码表:
CREATE TABLE Event
(
EventId INT IDENTITY(1,1) CONSTRAINT pk_Event PRIMARY KEY,
ConferenceId INT NOT NULL,
FOREIGN KEY (ConferenceId) REFERENCES Conference(ConferenceId),
RoomId INT,
FOREIGN KEY (RoomId) REFERENCES Room(RoomId),
BeginDate DATETIME NOT NULL,
EndDate DATETIME NOT NULL,
Title VARCHAR(200) NOT NULL,
Description VARCHAR(2000) NOT NULL,
CONSTRAINT date_ck CHECK (DATEDIFF(MINUTE, beginDate, endDate) > 0
AND DATEDIFF(HOUR, beginDate, endDate) <= 5)
);
现在,我正在尝试创建一个触发器,以防止添加两个时间重叠的事件,现在两个事件可以同时发生。我有这样的东西:
CREATE TRIGGER CheckTwoEventsForOverlapingTime
ON [dbo].Event
AFTER INSERT, UPDATE
AS
IF EXISTS(SELECT begindate, enddate
FROM Event e
WHERE e.conferenceId in (SELECT ConferenceId FROM inserted)
AND ((SELECT BeginDate FROM inserted) > BeginDate
AND (SELECT BeginDate FROM inserted) <= EndDate) OR
((SELECT EndDate FROM inserted) >= BeginDate
AND (SELECT EndDate FROM inserted) < EndDate) OR
((SELECT BeginDate FROM inserted) < BeginDate
AND (SELECT EndDate FROM inserted) > EndDate))
BEGIN
RAISERROR('No two events can take place at the same time.', 16, 1)
ROLLBACK
END
GO
可悲的是,这不想起作用。如果事件A从10AM开始持续到1PM,当我尝试添加事件B,该事件B从10AM开始但持续到2PM时,它不会抛出错误。我不知道怎么了。
答案 0 :(得分:2)
嗯。我认为逻辑是:
if exists (select 1
from event e join
inserted i
on i.conferenceId = e.conferenceId and
i.begindate <= e.enddate and
i.enddate >= e.begindate
)
begin
raiseerror('No two events can take place at the same time.', 16, 1);
rollback;
end;
逻辑是,当一个事件在第二个结束之前(在或结束时)开始,而在第二个结束之后的第一个结束(在或结束时)时,两个事件重叠。
rollback
是多余的-代码永远不会在那里。
<=
/ <
和>=
/ >
上的确切逻辑取决于您如何定义重叠。如果允许一个事件恰好在第二个事件开始时才结束,那么请改用<
/ >
。
答案 1 :(得分:2)
您必须检查两组。首先,inserted
集中不得有任何重叠的事件。然后,inserted
与未更改但仍保留的集合(即表中已存在但deleted
中没有的集合)之间不得有任何重叠事件。
...
IF EXISTS (SELECT *
FROM inserted i1
INNER JOIN inserted i2
ON i1.conferenceid = i2.conferenceid
AND i1.eventid <> i2.eventid
AND i1.enddate > i2.begindate
AND i1.begindate < i2.enddate)
OR EXISTS (SELECT *
FROM (SELECT *
FROM event e1
WHERE NOT EXISTS (SELECT *
FROM deleted d1
WHERE d1.eventid = e1.eventid) e2
INNER JOIN inserted i2
ON e2.conferenceid = i2.conferenceid
AND e2.eventid <> i2.eventid
AND e2.enddate > i2.begindate
AND e2.begindate < i2.enddate))
BEGIN
THROW 50000, 'No two events can take place at the same time.', 1;
END;
...
我还根据manual的说明将RAISERROR
更改为THROW
:
新应用程序应改用THROW。