如何确保数据库中的 startDate 和 endDate 列不重叠?
Posted
技术标签:
【中文标题】如何确保数据库中的 startDate 和 endDate 列不重叠?【英文标题】:How to ensure non overlapping startDate and endDate columns in database? 【发布时间】:2021-12-21 05:34:58 【问题描述】:下表存储了不同日期范围内的产品价格
id
productID
startDate
endDate
price
如何在数据库级别确保给定日期没有多个条目。 (MongoDB / mysql)
正确设置
startDate endDate
2020-01-01 2020-01-05
2020-01-07 2020-01-07
2020-01-08 2020-01-20
不正确的设置
日期 2020-01-04 有两个条目(第一个和第二个)
startDate endDate
2020-01-01 2020-01-05
2020-01-04 2020-01-07
2020-01-08 2020-01-20
【问题讨论】:
我猜你需要一个触发器。 您是否希望 (1) 确保当前数据没有重叠 (2) 以防止与现有行重叠的行插入? 如果 2 个范围重叠,则下一个表达式为真:start1 < end2 AND start2 < end1
。
@SalmanA 什么样的触发器?
@Akina 我想在插入时确保。此表中的每个新插入都会导致更新/插入/删除操作的组合。例如,在正确的 SET 中,如果我想添加第 5 到 25 的条目,则需要更新第 1 条目,删除第 2 和第 3 条目并为 21 到 25 日创建新条目。我想确保这个表永远不会得到重叠的条目。如果我在每次操作后都执行验证查询,那么这将导致过多的开销,因为在此表中每小时会发生数百次插入。
【参考方案1】:
CREATE TRIGGER check_for_overlapping
BEFORE INSERT
ON prices
FOR EACH ROW
BEGIN
IF EXISTS ( SELECT NULL
FROM prices
WHERE prices.productID = NEW.productID
AND prices.startDate <= NEW.EndDate
AND NEW.startDate <= prices.EndDate ) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Entered data overlaps with existing data';
END IF;
END;
DEMO
【讨论】:
【参考方案2】:更改架构。
说真的。你有多余的信息。并且缺少信息(参见“2020-01-6”)。
不要有开始和结束,只有开始。 (等效地,您只能有一个“结束”日期。)
一个条目的“结束”由下一行的“开始”给出。 (见下例)
因为你似乎有未分配的日子;在那段时间(例如,2020-01-06)“产品”是否不可用?如果这是有效的业务逻辑,请添加一行以某种方式表明这种情况。
对于 IP 地址范围,我执行了上述操作。 (并且间隙是有效的——它们指的是“未分配的”IP。)参见http://mysql.rjweb.org/doc.php/ipranges。它包括许多需要从“ip-address”调整为“date”的操作(插入、查找、修改等)的代码。
正如 Akina 指出的,责任在于插入代码,以确保数据符合业务逻辑规则。
在您的示例中,2020-01-07 2020-01-07
的意思是“所有 7 个”吗?如果是这样,那么它在逻辑上是>= '2020-01-07' AND < '2020-01-08'
。这适用于我的 IP 类比等。
请注意,我选择为所有操作存储例程。这避免了“每次操作后执行验证查询”的需要
【讨论】:
以上是关于如何确保数据库中的 startDate 和 endDate 列不重叠?的主要内容,如果未能解决你的问题,请参考以下文章