你不能在桌子上这样做,不,因为没有什么可以让UNIQUE 开启。
但是,您可以做的是使用 VIEW 来强制执行它。
首先,让我们创建您的表格。我假设列datetime,实际上应该是begin 和end;我建议不要使用这些名称,因为它们是保留关键字。因此,我称他们为DateBegin 和DateEnd。我还假设它们只是日期(没有时间部分)值,因此将它们定义为 date 而不是 datetime:
CREATE TABLE dbo.mytable(ID int primary key,
Value int,
[BeginDate] date NULL,
[EndEnd] date NULL);
我们将INSERT您的前 2 行,因为它们“正常”:
INSERT INTO dbo.mytable (ID, Value, BeginDate, EndDate)
VALUES(1, 1, '20210723', '20210724'),
(2, 1, '20210725', NULL);
现在我们需要创建一个VIEW,但我们需要每个日期一行。因此,您需要创建一个日历表。我不打算在这里介绍如何创建一篇文章,但实际上有 100 篇文章,例如 SQL Server Central 上的文章:Bones of SQL - The Calendar Table、Calendar Tables in T-SQL。
一旦您有了日历表,您就可以在下面创建VIEW,其中JOIN将您表中的数据发送到日历表。我们将让VIEW 只返回列value 和日期。我们还将对其进行模式绑定;这意味着我们可以向其添加UNIQUE INDEX:
CREATE VIEW dbo.MyView
WITH SCHEMABINDING
AS
SELECT MT.[Value],
CT.CalendarDate
FROM dbo.MyTable MT
JOIN dbo.CalendarTable CT ON MT.BeginDate <= CT.CalendarDate --I assume, despite your schema, MT.BeginDate can't be NULL
AND (MT.EndDate >= CT.CalendarDate OR MT.EndDate IS NULL);
现在我们有一个VIEW,每个日期和每个值都有一行。这意味着我们现在可以创建我们的UNIQUE INDEX:
CREATE UNIQUE CLUSTERED INDEX MyIndex ON dbo.MyView ([Value], CalendarDate);
现在,如果我们尝试 INSERT 同一日期和值的行,我们将收到错误:
INSERT INTO dbo.MyTable (ID, Value, BeginDate, EndDate)
VALUES(3, 1, '20210720', '20210723');
无法在具有唯一索引“MyIndex”的对象“dbo.MyView”中插入重复的键行。重复键值为 (1, 2021-07-23)。