开放时间数据库设计

发布于 2024-10-13 18:52:54 字数 376 浏览 13 评论 0原文

我们目前正在开发一个应用程序,其中多个实体具有关联的开放时间。开放时间可能跨越多天,也可能在一天之内。

前任。周一 6:00 开市,周五 18:00 闭市。

或者

周一 06:00 开放,周一 15:00 关闭。

此外,一个实体每天可能有多组开放时间。 到目前为止,我发现的最好的设计是定义一个开放时间,由以下内容组成:

StartDay、StartTime、EndDay 和 EndTime。

这种设计可以实现所有所需的灵活性。然而,数据完整性成为一个问题。我似乎找不到一个不允许重叠跨度(在数据库中)的解决方案。

请分享您的想法。

编辑:数据库是 Microsoft SQL Server 2008 R2

We are currently developing an application in which multiple entities have associated opening hours. Opening hours may span multiple days, or may be contained within a single day.

Ex. Opens Monday at 6:00 and closes at Friday at 18:00.

Or

Opens Monday at 06:00 and closes Monday at 15:00.

Also, an entity may have multiple sets of opening hours per day.
So far, the best design I have found, is to define an opening hour to consist of the following:

StartDay, StartTime, EndDay and EndTime.

This design allows for all the needed flexibility. However, data integrity becomes an issue. I cannot seem to find a solution that will disallow overlapping spans (in the database).

Please share your thoughts.

EDIT: The database is Microsoft SQL Server 2008 R2

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

一桥轻雨一伞开 2024-10-20 18:52:54

考虑存储您的 StartDay 和 StartTime,然后为其打开的小时数设置一个值。这将确保您的截止日期时间在开盘之后。

OpenDate -- day of week? e.g. 1 for Monday
OpenTime -- time of day. e.g. 08:00
DurationInHours -- in hours or mins. e.g.   15.5

Consider storing your StartDay and StartTime, but then have a value for the number of hours that it's open. This will ensure that your closing datetime is after the opening.

OpenDate -- day of week? e.g. 1 for Monday
OpenTime -- time of day. e.g. 08:00
DurationInHours -- in hours or mins. e.g.   15.5
最终幸福 2024-10-20 18:52:54

假设有一个强大的触发器框架,

在插入/更新时,您将检查新的开始或结束日期是否在任何现有范围内。如果确实如此,那么您将回滚更改。

CREATE TRIGGER [dbo].[mytable_iutrig] on [mytable] FOR INSERT, UPDATE AS

IF (SELECT COUNT(*)
FROM inserted, mytable
WHERE (inserted.startdate < mytable.enddate 
          AND inserted.startdate > mytable.startdate)
      OR (inserted.enddate < mytable.enddate 
          AND inserted.enddate > mytable.startdate)) > 0 
BEGIN
    RAISERROR --error number
    ROLLBACK TRANSACTION
END

Presuming a robust trigger framework

On insert/update you would check if the new start or end date falls inside of any existing range. If it does then you would roll back the change.

CREATE TRIGGER [dbo].[mytable_iutrig] on [mytable] FOR INSERT, UPDATE AS

IF (SELECT COUNT(*)
FROM inserted, mytable
WHERE (inserted.startdate < mytable.enddate 
          AND inserted.startdate > mytable.startdate)
      OR (inserted.enddate < mytable.enddate 
          AND inserted.enddate > mytable.startdate)) > 0 
BEGIN
    RAISERROR --error number
    ROLLBACK TRANSACTION
END
鲜肉鲜肉永远不皱 2024-10-20 18:52:54

检测和防止重叠时间段必须在应用程序级别完成。当然,您可以尝试在数据库中使用触发器,但在我看来这不是数据库问题。您想出的结构很好,但是您的应用程序逻辑必须处理重叠问题。

Detecting and preventing overlapping time periods will have to be done at the application level. Of course you can attempt to use a trigger in the database but in my opinion this is not a database issue. The structure that you came up with is fine, but your application logic will have to take care of the overlap.

随风而去 2024-10-20 18:52:54

SimpleTalk 网站上有一篇 Joe Celko 撰写的文章,内容为 这里讨论了类似的问题,并提出了一个优雅但复杂的解决方案。这可能适用于您的情况。

There's an article by Joe Celko on the SimpleTalk website, over here, that discusses a similar issue, and presents am elegant if complex solution. This is probably applicable to your situation.

忘东忘西忘不掉你 2024-10-20 18:52:54

具有单列 TimeOfChangeBetweenOpeningAndClosing 的表?

但更严重的是,我可能不会太担心提出一个单一的数据库结构来表示所有内容,最终您可能想要一个涉及重复、计划关闭等的系统。持久化表示这些的对象,然后评估它们以找到关闭/开放时间。

A table with a single column TimeOfChangeBetweenOpeningAndClosing?

More seriously though, I would probably not worry too much about coming up with a single database structure for representing everything, eventually you'll probably want want a system involving recurrences, planned closures etc. Persist objects representing those, and then evaluate them to find out the closing/opening times.

以为你会在 2024-10-20 18:52:54

这看起来是一个很好的解决方案,但您必须编写一个自定义验证函数。内置的数据库验证(即唯一、小于 x 等)不会在这里解决它。为了确保没有重叠的跨度,每次将记录插入数据库时​​,您都必须选择现有记录并进行比较...

This looks like a good solution, but you'll have to write a custom validation function. The built in database validation (i.e. unique, less than x, etc.) isn't going to cut it here. To ensure you don't have overlapping spans, every time you insert a record into the database, you're going to have to select existing records and compare...

终陌 2024-10-20 18:52:54

首先是逻辑,如果一个跨度的起始值落在另一个跨度的开始/结束之间,则两个跨度将重叠。如果我们将日期时间组合起来,而不是日期 1、时间 1 和日期 2、时间 2,这会容易得多。因此,查找重叠的查询如下所示。

select openingId
  from opening o1
  join opening o2 on o1.startDateTime 
             between o2.startDateTime
                 AND o2.endDateTime

您可以将其放入触发器中,并在找到匹配项时抛出错误。

First the logic, two spans will overlap if the start value of one falls between the start/end of the other. This is much easier if we have datetimes combined, instead of date1,time1 and date2,time2. So a query to find an overlap looks like this.

select openingId
  from opening o1
  join opening o2 on o1.startDateTime 
             between o2.startDateTime
                 AND o2.endDateTime

You can put this into a trigger and throw an error if a match is found.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文