2014-10-10 117 views
0

我正在编写一个应用程序,允许人们发送短信,如果我们认识到他们发送的单词,我们会做一些事情。我们认识到的关键词(句柄)会根据日期发生变化。例如,我工作的教会总是需要很多复活节志愿者,所以在复活节前两个月,我们想要指定“复活节”作为关键字,在复活节后我们要禁用它。因此主键需要为<keyword, date-range>。我可以将其设置为<keyword, date-start, date-end>,但如果我尝试插入具有相同关键字的新记录并且在另一个记录之间使用日期开始或日期结束,我希望存在PK冲突(或至少某种类型的约束冲突)行的日期开始和日期结束。SQL Server主键使用日期范围

我最好的行动方式是什么? SQL Server是否具有内置的此功能?我是否需要使用.NET创建某种自定义类型?我是使用主键还是辅助检查约束来做到这一点?

我总是喜欢优化速度,但事实上,这个应用程序并不需要它。

+0

没有什么建在所有你需要做的是创造。用于术语和日期过滤器的表格。 – durbnpoisn 2014-10-10 16:09:32

+0

@durbnpoisn你是什么意思的日期过滤器? – dfoverdx 2014-10-10 16:16:31

+0

您运行一条select语句,其中包括“where [dateIs]介于[beginDate]和[endDate]之间”。你通过今天的日期。您的表格将具有关键字在这些范围内显示的开始日期和结束日期。 – durbnpoisn 2014-10-10 16:22:42

回答

2

除非我失去了一些重要的事情,我相信你可以使用check约束与函数配对实现这一点:

-- test table 
CREATE TABLE keyword_ranges (Keyword varchar(10), Startdate date, Enddate date); 

-- function that checks if ranges overlap 
CREATE FUNCTION CheckKeywordRange 
    (@Keyword VARCHAR(10), @Startdate date, @Enddate date) 
RETURNS int 
AS 
BEGIN 
    DECLARE @retval int 
     SELECT @retval = COUNT(*) 
     FROM keyword_ranges 
     WHERE keyword = @Keyword 
     AND 
     (@Startdate <= Enddate) and (@Enddate >= Startdate) 
    RETURN @retval 
END; 
GO 

-- constraint that calls the function 
ALTER TABLE keyword_ranges 
ADD CONSTRAINT chkKeywordRange 
CHECK (dbo.CheckKeywordRange(Keyword, Startdate, Enddate) = 1); 

-- this insert will succeed 
INSERT keyword_ranges VALUES ('Holiday', '2014-01-01', '2014-01-05') 
-- this insert will conflict with the check and fail 
INSERT keyword_ranges VALUES ('Holiday', '2014-01-03', '2014-01-07') 

Sample SQL Fiddle

+0

这基本上是我最终做的,虽然不是检查count是1,而是包含一个keyword_id int,在WHERE子句中,我确保被检查的行不是被插入的行。 – dfoverdx 2014-10-10 17:40:58

2

您可能需要在应用程序级别执行此操作,而不是Sql Server级别。 Sql Server可以强制执行范围,但只有在每个范围都计算为固定规范的开始时间和长度时(即:始终有2个月范围始终在偶数月的第一天开始)。如果你想要任意的开始时间或者长度,你就会被困在应用程序逻辑中,或者最好是在触发器中。

+0

是否有可能通过检查约束来完成它?类似'... CHECK(NOT EXISTS(SELECT 1 FROM keywords k WHERE k.word = word AND(date_start BETWEEN k.date_start AND k.date_end OR date_end BETWEEN k.date_start AND k.date_end))' – dfoverdx 2014-10-10 16:13:52

+0

With SQL server你必须使用一个触发器,因为Joel说。检查约束只在行级别 – jazzytomato 2014-10-10 16:31:29

+0

和btw你的重叠检查条件是错误的,如果你插入一行开始之前和结束后一个现有的记录?这里很好的解释:http ://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap – jazzytomato 2014-10-10 16:36:27