我有以下表结构:
表名:avail
id (autoincremetn) | acc_id | start_date | end_date
-------------------------------------------------------
1 | 175 | 2015-05-26 | 2015-05-31 |
-------------------------------------------------------
2 | 175 | 2015-07-01 | 2015-07-07 |
-------------------------------------------------------
它用于定义日期范围可用性,例如。 start_date和end_date之间的所有日期都不可用于给定的acc_id。
根据用户输入我正在关闭不同的范围,但我想抛出一个错误,如果用户试图关闭(提交)一个范围,它已经开始或者在一个已经存在的范围内的某个地方的end_date(对于在DB中提交了acc_id)。 在这个例子中,start_date:2015-05-30 end_date:2015-06-04将是一个很好的失败候选者。
我发现了这个QA: MySQL overlapping dates, none conflicting
几乎解释了如何分两步完成,两次查询之间有一些PHP逻辑。
但我想知道是否可以在一个插入语句中完成。 我最终会检查因成功或失败而受影响的行(子问题:是否有更方便的方法来检查除了日期重叠之外是否因其他原因而失败?)
修改:
为回应彼得的评论,我将进一步指明验证:
应该避免任何形式的重叠,即使是那个拥抱的人 整个范围或发现自己在现有范围内。另外,如果 开始或结束日期等于必须的现有开始日期或结束日期 考虑重叠。有时某些acc_id已经有了更多 比表中的一个响应所以应该进行验证 具有给定acc_id的所有条目。
答案 0 :(得分:-1)
可悲的是,使用MySQL这是不可能的。或者至少,实际上。首选方法是使用SQL CHECK约束,这些约束是SQL语言标准。但是,MySQL不支持它们。
请参阅:https://dev.mysql.com/doc/refman/5.7/en/create-table.html
CHECK子句被解析但被所有存储引擎忽略。
似乎PostgreSQL确实支持表上的CHECK约束,但我不确定切换数据库引擎的可行性如何,或者即使使用该功能也是值得的。
在MySQL中,可以使用触发器来解决此问题,该问题将在插入/更新发生之前检查重叠行,并使用SIGNAL
语句抛出错误。 (请参阅:https://dev.mysql.com/doc/refman/5.7/en/signal.html)但是,要使用此解决方案,您必须使用最新的MySQL版本。
除了纯SQL解决方案之外,这通常是在应用程序逻辑中完成的,因此访问MySQL数据库的任何程序通常都会通过请求SELECT COUNT(id) ...
中新条目违反的每一行来检查这些约束。声明。如果返回的计数大于0,则根本不会插入/更新。