我有很多情况下我的数据库结构类似于:
TABLE事件(EventID INT PrimaryKey,Start DATETIME,Finish DATETIME);和 TABLE EventTask(EventTaskID INT PrimaryKey,EventID INT ForeignKey,TaskStart DATETIME,TaskFinish DATETIME)
事件和EventTasks等之间的1对多关系
当事件表中的日期发生变化时,还需要更改EventTask日期 - 使用提供的日期函数并不困难,但日期操作总是有点棘手。
我想知道用两个INTS替换TaskStart DATETIME和TaskFinish DATETIME是否更好:一个用于Event.Start偏移(不同于Event.Start的分钟)和一个持续时间。
这样日期更新变得更加健壮,因为只有一行需要更新。
(我规定这仅适用于EventTask日期绝对取决于事件日期的情况)
答案 0 :(得分:2)
是的,这对我来说听起来完全合理。主要的缺点是,为了找到EventTasks的实际时间,你必须执行计算。这将减慢返回时间的任何事情,特别是会损害过滤器中涉及EventTask时间的查询 - 例如“找到在X和Y之间发生的所有任务。”那些以前可以使用索引,但不能再使用索引了。
答案 1 :(得分:1)
如果您使用的是SQL 2008,则可以使用datetimeoffset数据类型。
如果你想“直接”获取数据,没有太多麻烦你可以使用computed columns,但如果结果你可能无法创建索引(或使它们存储结果)是不确定的。
你的结构是这样的:
TABLE [Event] (
EventID INT PrimaryKey,
Start DATETIME,
Finish DATETIME)
TABLE [EventTask](
EventTaskID INT PrimaryKey,
EventID INT ForeignKey,
TaskStart DATETIMEOFFSET,
TaskFinish DATETIMEOFFSET,
EventTaskStart as [getStartDateByEvent](eventId, TaskStart) <PERSISTED>,
EventTaskStop as [getStopDateByEvent](eventId, TaskStart) <PERSISTED>,
)
FUNCTION [getStartDateByEvent](eventId, TaskStart) as DATETIME
BEGIN
SELECT [EVENT].start + TaskStart from [EVENT] WHERE [EVENT].EVENTID = eventID
END
FUNCTION [getStartDateByEvent](eventId, TaskStop) as DATETIME
BEGIN
SELECT [EVENT].[finish] + TaskStop from [EVENT] WHERE [EVENT].EVENTID = eventID
END
答案 2 :(得分:0)
Jon Skeet:
执行计算。那会的 减慢任何返回的东西 时间,尤其会伤害 涉及EventTask时间的查询 过滤器 - 例如“找到我所有的任务 这发生在时间X和Y之间。“
在我看来,在编写基本数据完整性约束时,您已经有了这个要求,例如:事件的任务日期必须在事件本身的日期内,例如将您的架构扩展为SQL DLL:
CREATE TABLE Event
(
EventID INTEGER NOT NULL PRIMARY KEY,
event_Start DATETIME NOT NULL,
event_Finish DATETIME NOT NULL,
CHECK (event_Start < event_Finish),
UNIQUE (event_Start, event_Finish, EventID)
)
CREATE TABLE EventTask
(
EventTaskID INTEGER NOT NULL PRIMARY KEY,
EventID INTEGER NOT NULL,
event_Start DATETIME NOT NULL,
event_Finish DATETIME NOT NULL,
FOREIGN KEY (event_Start, event_Finish, EventID)
REFERENCES Event (event_Start, event_Finish, EventID)
ON DELETE CASCADE
ON UPDATE CASCADE,
event_task_START DATETIME NOT NULL,
event_task_Finish DATETIME NOT NULL,
CHECK (event_task_Start < event_task_Finish),
CHECK (event_Start <= event_task_Start),
CHECK (event_Finish <= event_task_Finish)
);
如果一个事件的任务是顺序的,那么你还需要编写一个约束来防止重叠周期,这将涉及一个子查询(大多数SQL产品不支持CHECK
约束,例如在SQL Server中你会需要诉诸触发器)。如果必须使用时态函数(DATEADD
等)重新计算偏移量,那么在高活动环境中性能可能是一个问题,更不用说SQL DLL代码中增加的复杂性了。
由于这些原因,我会根据您的规范建议使用开始和结束数据对建模周期。