首先,看看这个非常相似的问题:Unique date range fields in SQL Server 2008
上述问题的答案(由David Hall提供)是我需要的 90%,只需一个小小的 ommision,举个例子:
--#### Create example table
CREATE TABLE [dbo].[tbl_Example](
[ID] [int] IDENTITY(1,1) NOT NULL,
[StockCode] [varchar](20) NOT NULL,
[ValidFrom] [datetime] NOT NULL,
[ValidUntil] [datetime] NOT NULL,
[Type] [char](1) NOT NULL,
CONSTRAINT [PK_tbl_Example] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
--#### Add the trigger (based on David Halls answer - I allow duplicate date ranges as long as the StockCode or Type differ)
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[DateRangeTrigger] ON [dbo].[tbl_Example]
FOR INSERT, UPDATE
AS
BEGIN
IF EXISTS ( SELECT t.ValidFrom ,
t.ValidUntil
FROM tbl_Example t
JOIN inserted i ON ( i.StockCode = t.StockCode
AND i.Type = t.Type
AND i.ValidFrom > t.ValidFrom
AND i.ValidFrom < t.ValidUntil
AND i.id <> t.id
)
OR ( i.StockCode = t.StockCode
AND i.Type = t.Type
AND i.ValidUntil < t.ValidUntil
AND i.ValidUntil > t.ValidFrom
AND i.id <> t.id
)
OR ( i.StockCode = t.StockCode
AND i.Type = t.Type
AND i.ValidFrom < t.ValidFrom
AND i.ValidUntil > t.ValidUntil
AND i.id <> t.id
) )
BEGIN
RAISERROR ('Date range cant overlap existing date ranges for given StockCode and Type', 16, 1)
IF ( @@TRANCOUNT > 0 )
ROLLBACK
END
END
GO
--#### Problem: its allowing duplicate date ranges where Start and End Dates are 100% equal
INSERT [dbo].[tbl_Example] ([StockCode], [ValidFrom], [ValidUntil], [Type]) VALUES (N'Test', CAST(0x0000A13900000000 AS DateTime), CAST(0x0000A13B00000000 AS DateTime), N'O')
INSERT [dbo].[tbl_Example] ([StockCode], [ValidFrom], [ValidUntil], [Type]) VALUES (N'Test', CAST(0x0000A13900000000 AS DateTime), CAST(0x0000A13B00000000 AS DateTime), N'O')
您会注意到,使用 Dave 的触发器,如果[ValidFrom]
or[ValidUntil]
相等,我仍然可以插入重叠日期。
缺少向触发器添加加载更多OR
子句以说明匹配开始或匹配结束或两者 - 调整触发器以防止最后一个子句的最简单方法是什么?
为了澄清,我试图防止的重叠如下: