SQL Server唯一键约束日期/时间跨度

时间:2015-10-08 23:56:37

标签: sql-server sql-server-2014

如何为下表设置唯一键约束,以确保Date / BeginTime和Date / EndTime之间的日期/时间跨度不与其他记录重叠?如果我需要添加一个计算列,那么数据类型和计算是什么?

Column Name   Data Type
Date          date
BeginTime     time(7)
EndTime       time(7)

感谢。

3 个答案:

答案 0 :(得分:3)

我不相信你可以在SQL Server中使用UNIQUE约束来做到这一点。 Postgres具有此功能,但要在SQL Server中实现它,您必须使用触发器。由于您的问题是“如何使用唯一键约束来执行此操作”,因此正确的答案是“您不能”。如果您曾问过“我如何强制执行此非重叠约束”,那么就有答案。

答案 1 :(得分:3)

Alexander Kuznetsov展示了一种可行的方式。 Storing intervals of time with no overlaps

参见Joe Celko的文章:Contiguous Time Periods

这是表格和第一个间隔:

CREATE TABLE dbo.IntegerSettings(SettingID INT NOT NULL,
  IntValue INT NOT NULL,
  StartedAt DATETIME NOT NULL,
  FinishedAt DATETIME NOT NULL,
  PreviousFinishedAt DATETIME NULL,

  CONSTRAINT PK_IntegerSettings_SettingID_FinishedAt 
      PRIMARY KEY(SettingID, FinishedAt),

  CONSTRAINT UNQ_IntegerSettings_SettingID_PreviousFinishedAt
      UNIQUE(SettingID, PreviousFinishedAt),

  CONSTRAINT FK_IntegerSettings_SettingID_PreviousFinishedAt
    FOREIGN KEY(SettingID, PreviousFinishedAt)
    REFERENCES dbo.IntegerSettings(SettingID, FinishedAt),

  CONSTRAINT CHK_IntegerSettings_PreviousFinishedAt_NotAfter_StartedAt
      CHECK(PreviousFinishedAt <= StartedAt),

  CONSTRAINT CHK_IntegerSettings_StartedAt_Before_FinishedAt 
      CHECK(StartedAt < FinishedAt)
);

INSERT INTO dbo.IntegerSettings
    (SettingID, IntValue, StartedAt, FinishedAt, PreviousFinishedAt)
VALUES(1, 1, '20070101', '20070103', NULL);

约束强制执行这些规则:

  • 设置
  • 只能有一个第一个间隔
  • 下一个窗口必须在上一个窗口结束后开始
  • 两个不同的窗口不能引用与前一个窗口相同的窗口

答案 2 :(得分:0)

-- this is a unique key that allows for null in EndTime field
--  This Unique Index could be clusteres optionally instead of the traditional primary key being clustered 
CREATE UNIQUE NONCLUSTERED INDEX  
[UNQ_IDX_Date_BeginTm_EndTm_UniqueIndex_With_Null_EndTime] ON [MyTableName]
(
    [Date] ASC,
    [BeginTime] ASC,
    [EndTime] ASC
) 

GO


-- this is a traditional PK Constraint that is clustered but EndTime is
--- Not Null
-- it is possible that this table would not have a traditional Primary Key
ALTER TABLE dbo.MyTable ADD CONSTRAINT
    PK_Date_BeginTm_EndTm_EndTimeIsNotNull PRIMARY KEY CLUSTERED 
    (
    Date,
    BeginTime,
    EndTime
    ) 

GO

-- HINT - Control your BeginTime and EndTime secconds and milliseconds at 
-- all insert and read points 
-- you want 13:01:42.000  and 13:01:42.333  to evaluate and compare the
-- exact way you expect from a KEY perspective