SQL Server约束日期范围

时间:2017-03-02 18:04:04

标签: sql-server date range constraints

我试图通过开始日期和结束日期限制SQL Server数据库,以便我永远不会双重预订资源(即没有重叠或重复的预订)。

假设我的资源已编号,使得表格看起来像  ResourceId,StartDate,EndDate,Status

所以我想说我有资源#1。我想确保我不能预订2017年1月8日至2017年1月16日以及相同资源的1/10/2017 - 1/18/2017的单独预订。

更复杂的是,资源的StartDate可以与资源的EndDate相同。因此,1/8/277至2017年1月16日和1月16日至2017年1月20日是可以的(即,一个人可以在同一天办理另一个人结账登记)。

此外,“状态”字段指示资源的预订是“活动”还是“已取消”。所以我们可以忽略所有取消的预订。

我们在保存时保护了Code(存储过程和C#)中的这些重叠或双重预订,但我们希望通过添加DB Contraint来增加额外的保护层。

这在SQL Server中是否可行?

先谢谢

2 个答案:

答案 0 :(得分:0)

您可以使用CHECK约束来确保startdate足够容易在EndDate之前或之前:

CONSTRAINT [CK_Tablename_ValidDates] CHECK ([EndDate] >= [StartDate])

约束无助于防止重叠的日期范围。您可以使用TRIGGER通过创建FOR INSERT,UPDATE触发器来强制执行此操作,该触发器在检测到重复时回滚事务:

CREATE TRIGGER [TR_Tablename_NoOverlappingDates] FOR INSERT, UPDATE AS
IF EXISTS(SELECT * from inserted INNER JOIN [MyTable] ON blah blah blah ...) BEGIN 
    ROLLBACK TRANSACTION;
    RAISERROR('hey, no overlapping date ranges here, buddy', 16, 1);
    RETURN;
END

另一个选项是创建一个索引视图,该视图查找重复项,并在该视图上放置一个唯一约束,如果存在多个记录,则会违反该约束。这通常使用一个虚拟表来完成,该表具有2行笛卡尔连接到聚合视图,该聚合视图选择重复的id-因此,具有重复的一个记录将在视图中返回具有唯一索引的相同伪id值的两行。

我已经做到了,我更喜欢触发方式。

答案 1 :(得分:0)

在这里从这个答案中得出:Date range overlapping check constraint

首先,检查以确保不存在重叠:

pathToExe

如果一切都清楚,那么创建你的功能。

有几种不同的方式来编写函数,例如我们可以跳过const a = () => console.log('a'); var b = a; b = () => console.log('b'); a(); // prints 'b' // Define a constant reference/pointer to the static object oA const oA = { // Define mutable property "f" f: () => console.log('a') }; // Define an other const ref to the same object called oB const oB = oA; // Update the value pointed by the oB.f ref oB.f = () => console.log('b'); // Call oB.f // 'b' expected oB.f(); // Call oA.f // 'b' expected oA.f(); // Using Object.defineProperty Object.defineProperty(oA, 'f', { __proto__: null , value: () => console.log('f') }); // Call oB.f // 'f' expected oB.f(); // Call oA.f // 'f' expected oA.f();并使用仅基于select * from dbo.Reservation as r where exists ( select 1 from dbo.Reservation i where i.PersonId = r.PersonId and i.ReservationId != r.ReservationId and isnull(i.EndDate,'20990101') > r.StartDate and isnull(r.EndDate,'20990101') > i.StartDate ); go 的内容,就像上面的查询一样,但我会以此为例:

StartDate

然后添加约束:

EndDate

最后:测试一下。