1

我有一个由代码给出的表格:

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 从上午 10 点开始持续到下午 1 点,当我尝试添加从上午 10 点开始但持续到下午 2 点的事件 B 时,它不会引发错误。我不知道怎么了。

4

2 回答 2

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是多余的——代码永远不会在那里。

<=/<>=/的确切逻辑>取决于您如何定义重叠。如果允许一个事件恰好在第二个事件开始时结束,则使用</>代替。

于 2018-12-25T16:19:17.970 回答
2

你必须检查两组。首先,集合中不能有任何重叠的事件insertedinserted然后在 the和未触及但仍保留的集合之间不能有任何重叠事件,即已经在表中但不在 中的集合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;
...

正如手册所述,我也更改RAISERROR为 a :THROW

新应用程序应该使用THROW

于 2018-12-25T17:00:40.677 回答