SQL 服务器唯一键约束 Date/Time 跨度
SQL Server Unique Key Constraint Date/Time Span
如何为以下 table 设置唯一键约束以确保 Date/BeginTime 和 Date/EndTime 之间的 date/time 跨度不与其他记录重叠?如果我需要添加一个计算列,什么数据类型和计算?
Column Name Data Type
Date date
BeginTime time(7)
EndTime time(7)
谢谢。
我认为您无法在 SQL 服务器中使用 UNIQUE 约束来做到这一点。 Postgres 具有此功能,但要在 SQL 服务器中实现它,您必须使用触发器。由于您的问题是 "how can I do this using a unique key constraint",因此正确答案是 "you can't"。如果你问过 "how can I enforce this non-overlapping constraint",这里有答案。
-- 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
Alexander Kuznetsov 展示了一种可能的方法。 Storing intervals of time with no overlaps.
另请参阅 Joe Celko 的文章:Contiguous Time Periods
这里是table和第一个区间:
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);
约束强制执行这些规则:
- 一个设置只能有一个第一个间隔
- 下一个window必须在上一个结束后开始
- 两个不同的 windows 不能引用一个和前一个 window 相同的
如何为以下 table 设置唯一键约束以确保 Date/BeginTime 和 Date/EndTime 之间的 date/time 跨度不与其他记录重叠?如果我需要添加一个计算列,什么数据类型和计算?
Column Name Data Type
Date date
BeginTime time(7)
EndTime time(7)
谢谢。
我认为您无法在 SQL 服务器中使用 UNIQUE 约束来做到这一点。 Postgres 具有此功能,但要在 SQL 服务器中实现它,您必须使用触发器。由于您的问题是 "how can I do this using a unique key constraint",因此正确答案是 "you can't"。如果你问过 "how can I enforce this non-overlapping constraint",这里有答案。
-- 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
Alexander Kuznetsov 展示了一种可能的方法。 Storing intervals of time with no overlaps.
另请参阅 Joe Celko 的文章:Contiguous Time Periods
这里是table和第一个区间:
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);
约束强制执行这些规则:
- 一个设置只能有一个第一个间隔
- 下一个window必须在上一个结束后开始
- 两个不同的 windows 不能引用一个和前一个 window 相同的