在(My)SQL数据库中存储事件时间的最佳方法

时间:2020-03-06 14:25:05  来源:igfitidea点击:

我正在尝试确定在MySQL数据库中存储事件时间的最佳方法。这些事件应尽可能灵活,并且能够表示"单个事件"(在某个时间开始,不一定需要结束时间),"全天"和"多天"事件,重复事件,重复全天事件,可能是"每月第3个星期六"类型的事件等。

请提出一些经过验证的数据库方案。

解决方案

cron会这样做吗?以此方式记录开始时间和结束时间。

表:事件

  • 开始时间(dateTime)
  • EndTime(dateTime)为null,无结束时间
  • RepeatUnit(int)null = noRepeat,1 =小时,2 =天,3 =周,4 = dayOfMonth,5 =月,6 =年
  • NthDayOfMonth(int)
  • RepeatMultiple(int),例如,将RepeatUnit设置为3,每两周将其设置为2
  • ID-如果需要,StartTime可能适合我们唯一地标识事件。
  • 名称(字符串)-为事件指定的名称

这可能会有所帮助。当重复出现时,需要大量的代码来解释。分辨率低于重复单位的部分时间字段必须忽略。做这个月的第三个星期六也不是一件容易的事……仅需要NthDayOfMonth信息才能执行这种功能。

与计算出重复出现的位置所需的代码相比,为此所需的数据库模式很简单。

我们需要两个表。一种用于存储重复事件(表重复事件),另一种用于存储事件(表事件)。简单条目仅存储在事件表中。重复条目存储在repeatevent表中,重复事件的所有单个条目也存储在事件表中。这意味着每次输入重复条目时,都必须输入所有单个结果条目。我们可以通过使用触发器或者作为业务逻辑的一部分来做到这一点。

这种方法的优点是查询事件很简单。它们都在事件表中。如果没有在事件表中存储重复事件,我们将拥有复杂的SQL或者业务逻辑,这将使系统运行缓慢。

create table repeatevent (
id int not null auto_increment, 
type int, // 0: daily, 1:weekly, 2: monthly, ....
starttime datetime not null, // starttime of the first event of the repetition
endtime datetime, // endtime of the first event of the repetition
allday int, // 0: no, 1: yes
until datetime, // endtime of the last event of the repetition
description varchar(30)
)

create table event (
id int not null auto_increment,
repeatevent null references repeatevent, // filled if created as part of a repeating event
starttime datetime not null,
endtime datetime,
allday int,
description varchar(30)
)

我开发了一个计划程序应用程序,该程序大致遵循iCalendar标准(用于记录事件)。我们可能需要阅读RFC 2445或者Apple Inc. icalendar架构发布的该架构,以查看它们是否与问题有关。

我的数据库架构(当时未考虑重复/全天事件)

event (event_id, # primary key
       dtstart,
       dtend,
       summary,
       categories,
       class,
       priority,
       summary,
       transp,
       created,
       calendar_id, # foreign key
       status,
       organizer_id, # foreign key
       comment,
       last_modified,
       location,
       uid);

上表中的外键calendar_id引用了这个

calendar(calendar_id, # primary key
         name);

organizer_id引用了这一点(缺少其他属性,例如通用名等)

organizer(organizer_id, # primary key
          name);

我们可能会发现其他可读性更高的文档位于此处

希望这可以帮助

使用datetime和mysql内置的NOW()函数。在过程开始时创建记录,在过程结束时更新跟踪结束时间的列。