首先,检查一下这个非常类似的问题:SQL Server2008中的唯一日期范围字段
上面的问题的答案是90%,我需要一个小口子,下面举个例子:
--#### 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')
你会注意到,与戴维鈥檚扳机的地方,我仍可以插入日期重叠如果任一[ValidFrom]或者[ValidUntil]是 相等的 。
[ValidFrom]
[ValidUntil]
OR缺少向触发器添加更多子句以说明匹配开始或匹配结束或两者兼而有之的方式-调整触发器以防止出现最后一个子句的最简单方法是什么?
OR
我认为这种情况更合适:
IF EXISTS ( SELECT * --No need to choose columns in an EXISTS FROM tbl_Example t1 inner join tbl_Example t2 on t1.StockCode = t2.StockCode and t1.Type = t2.Type and t1.ValidFrom < t2.ValidTo and t2.ValidFrom < t1.ValidTo and t1.ID <> t2.ID where t1.ID in (select ID from inserted)) BEGIN RAISERROR ('Date range cant overlap existing date ranges for given StockCode and Type', 16, 1) ROLLBACK --We're in a trigger, we *must* be in a transaction END
它使用更简单的条件来检测重叠-如果两行都在另一行结束之前开始,则存在重叠。