多个值之间的SQL约束

时间:2010-08-17 19:43:20

标签: sql sql-server sql-server-2005 tsql

这是我的表

Events
Start : Datetime
End : Datetime

我正在尝试确保新事件不会与之前输入的任何事件重叠。我承认我的SQL知识充其量只是新手。以下是一个让我接近的select语句,但我无法弄清楚如何将其变成约束(我会使用check吗?)

SELECT e.*
FROM Events
WHERE Start BETWEEN e.START and e.END
OR End BETWEEN new.START and new.END
OR (Start < e.Start and End > e.End)

我想如果像这样的东西返回任何重叠的东西。

编辑:更新了“sql”语句以涵盖我的逻辑失败。它很可能仍然很难形成。我非常感谢所有的帮助!

4 个答案:

答案 0 :(得分:4)

这实际上必须进入代码或触发器。约束仅在行级别运行

CREATE TRIGGER TRG_Events_INSERT On EventsFOR INSERT
AS
IF EXISTS (SELECT *
    FROM Events E
        JOIN
        INSERTED INS
         ON
           (E.Start Between INS.START and INS.END)
          OR
           (E.End Between INS.START and INS.END)
          OR
           (E.Start < INS.START and E.End > INS.END)

     WHERE
        E.Key <> INS.Key --already inserted at this point

BEGIN
   ROLLBACK TRAN
   --etc
END
GO

答案 1 :(得分:3)

您提供的SQL在语法上不正确 - 使用:

SELECT e.*
  FROM EVENTS e
 WHERE start BETWEEN e.START and e.END
    OR end BETWEEN e.START and e.END
    OR (start < e.START AND end > e.END)

BETWEEN具有包容性,并在所有数据库上保持一致。

答案 2 :(得分:1)

这可能取决于你正在使用的DBMS,但是这种约束通常需要使用触发器来实现,该触发器执行查询以确定插入/更新是否有效以及如果没有,则回滚交易。 CHECK约束通常只允许您引用“当前行”中的列。

SELECT *
FROM Events E
WHERE E.Start <= NEWEND
AND E.End >= NEWSTART

...将为您提供与之重叠的事件(如果您对'触摸'事件不感兴趣,请更改&lt; =和&gt; =与&lt;和&gt ;.)

答案 3 :(得分:0)

您可以做的是在连接中将表与自身进行比较。下面是一个如何做到这一点的例子。我评论了一些方面。取消注释以查看处理不同案例的进展情况。

编辑:如果您需要将此作为约束,请使用触发器。

edit2:对于SQL 2005,使用单独的插入语句替换插入语法。 祝你好运,

GJ

declare @event table (
    Id int,
    Start DateTime,
    Stop DateTime
)

insert  @event (Id, Start, Stop)
values  (1, '2010-08-01', '2010-08-02')
    ,(2, '2010-08-04', '2010-08-06')
    ,(3, '2010-08-05', '2010-08-08')    -- start fals within event 2
    --,(4, '2010-01-01', '2010-12-31')  -- overlaps with all of them
    --,(5, '2010-08-01', '2010-08-02')      -- equal to event 1

select  *
from    @event e1
        inner join @event e2 
            on  e1.Id != e2.Id          -- do not compare to itself
            and e2.Start >= e1.Start    -- events that have a start date
            and e2.Start <= e1.Stop