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

Best way to store event times in (My)SQL database

提问人:deceze 提问时间:9/19/2008 更新时间:11/17/2015 访问量:8291

问:

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

请提出一些久经考验的数据库方案。

MySQL 时间

评论

0赞 ksno 9/27/2016
对于这个问题,您过去选择了什么作为最佳解决方案?我也在寻找用于此目的的数据库方案。

答:

0赞 Shinhan 9/19/2008 #1

cron 也是这样做的?以这种方式记录开始和结束时间。

评论

0赞 deceze 9/19/2008
不,更像是 iCal。我只是还没有找到关于iCal如何确切地做事或如何在SQL中最好地表达这一点的可读描述。
5赞 Scott Langham 9/19/2008 #2

表:事件

  • 开始时间 (dateTime)
  • EndTime (dateTime) null 表示无结束时间
  • RepeatUnit (int) null = noRepeat,1 = 小时,2 = 天,3 = 周,4 = dayOfMonth,5 = 月,6 = 年
  • NthDayOfMonth (整数)
  • RepeatMultiple (int) 例如,将 RepeatUnit 设置为 3,每两周将其设置为 2
  • Id - 如果需要,StartTime 可能适合你唯一标识事件。
  • Name (string) - 指定给事件的名称(如果需要)

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

与计算重复位置所需的代码相比,此操作所需的数据库架构很简单。

评论

0赞 deceze 9/19/2008
你如何用它来存储一个全天的活动?我肯定想分开日期和时间,因为“24-12-2008 00:00:00”是模棱两可的......
0赞 Scott Langham 9/19/2008
StartTime = '24-12-2008 00:00:00' EndTime = '24-12-2008 23:59:59' 如果应用程序将全天事件视为特殊情况,则访问数据库的代码必须知道 00:00:00 的开始和 23:59:59 的结束表示特殊情况,请检查它们并设置 allDay 标志
0赞 Scott Langham 9/19/2008
或者添加列 allDay (int),如另一个答案中所述。
1赞 boes 9/19/2008 #3

您需要两个表。一个用于存储重复事件(表 repeatevent),另一个用于存储事件(表 event)。简单条目仅存储在事件表中。重复条目存储在 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)
)
4赞 Jeffrey04 9/19/2008 #4

我开发了一个计划器应用程序,它松散地遵循 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);

while 引用这个(缺少其他属性,如通用名称等)organizer_id

organizer(organizer_id, # primary key
          name); 

您可能会发现另一个更具可读性的文档位于此处

希望这会有所帮助

评论

0赞 Svish 1/18/2012
指向 icalendar 架构的链接似乎已更改。你能尝试更新它吗?
0赞 Jeffrey04 2/28/2012
我想你仍然可以寻找 RFC2445 :)
0赞 Jeffrey04 11/17/2015
@svish刚刚找到了指向(现已弃用)iCalendar 架构的更新链接,但不确定您是否仍然需要它
0赞 Svish 11/20/2015
@Jeffrey94我没有,但请更新您的答案,以防其他人这样做(或者我稍后在某个时候这样做;)
-2赞 Z99 9/19/2008 #5

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