2009-09-11 45 views
0

相关的日期我有,我也有类似的数据库结构相当多的情况:存储在SQL

表事件(事件ID INT的PrimaryKey,开始DATETIME,完成DATETIME);和 TABLE EventTask(EventTaskID INT的PrimaryKey,事件ID INT ForeignKey的,TaskStart DATETIME,TaskFinish DATETIME)

1至事件和EventTasks之间一对多的关系,等等

当在事件表中的日期改变时,EventTask日期也需要改变 - 提供的日期函数并不难,但日期操作总是有点棘手。

我想知道是否最好用两个INTS替换TaskStart DATETIME和TaskFinish DATETIME:一个用于Event.Start偏移量(与Event.Start不同)和一个持续时间。

这样,日期更新变得更加健壮,因为只有一行需要更新。

(我规定,这仅适用在EventTask日期是完全依赖于事件日期)

回答

2

是的,这听起来完全合理的给我。主要的缺点是为了找到EventTasks的实际时间,你必须执行计算。这会减慢返回时间的任何事情,并且特别会损害在过滤器中涉及EventTask时间的查询 - 例如“找到所有在时间X和Y之间发生的任务。”那些以前可能已经使用过索引,但无法再使用。

+0

重查询EventTask时间Jon。无论如何,'原创'设计需要重新创建视图;我想知道你是否可以在这个视图上应用索引(按照SQLS2008)? – realcals 2009-09-11 06:31:39

+0

@realcals:可能。我不知道它会有多高效。数据库工程师有时候会非常聪明的人:)无论如何,在你走得太远之前要测试一些东西,我会说。 – 2009-09-11 07:02:04

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 
+0

我看不出有什么帮助 - 它不会让你指定一个不同表中的字段的偏移量,是吗? – 2009-09-11 07:01:17

+0

您仍然必须计算该值。 您不能使用直接引用另一个表的计算列,但可以使用用户定义函数 – 2009-09-11 07:04:41

+0

以下是带datetime结果的计算列示例: http://stackoverflow.com/questions/246666/persisting-a- calculate-datetime-column-in-sql-server-2005/247092#247092 – 2009-09-11 07:07:56

0

乔恩斯基特:

进行计算。这将减慢任何返回 次的任何事物,并且特别会损害 涉及 中的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代码的复杂性了。

由于这些原因,我会使用开始和结束数据对按照您的规范建议进行建模。