我试图通过开始日期和结束日期限制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中是否可行?
先谢谢
答案 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
最后:测试一下。