确保Oracle行代表唯一的时间跨度

确保Oracle行代表唯一的时间跨度,oracle,plsql,check-constraints,Oracle,Plsql,Check Constraints,我必须在Oracle/PLSQL中创建一个进程。我必须验证我创建的新行的开始日期和结束日期之间的时间间隔不能与其他行的其他开始日期和结束日期相交 现在我需要检查每一行是否存在这种情况,如果它不符合要求,重复指令应该停止,然后显示一条消息,如“给定的时间间隔不正确” 我不知道如何在Oracle/PLSQL中重复说明,如果您能帮助我,我将不胜感激 我需要一个循环或类似的smth来验证表中的每一行,即date_hour_I和date_hour_e给出的时间间隔与其余行给出的其他时间间隔不相交。还有一个

我必须在Oracle/PLSQL中创建一个进程。我必须验证我创建的新行的开始日期和结束日期之间的时间间隔不能与其他行的其他开始日期和结束日期相交

现在我需要检查每一行是否存在这种情况,如果它不符合要求,重复指令应该停止,然后显示一条消息,如“给定的时间间隔不正确”

我不知道如何在Oracle/PLSQL中重复说明,如果您能帮助我,我将不胜感激


我需要一个循环或类似的smth来验证表中的每一行,即date_hour_I和date_hour_e给出的时间间隔与其余行给出的其他时间间隔不相交。还有一个规范……每行的日期对应于在给定的时间间隔内为客户理发的客户和员工……我不想让引入新行,如果是针对同一客户(或其他客户)和员工,新的时间间隔与同一个/其他客户和员工的其他时间间隔相交……我希望我清楚地说明了……

为什么要检查每一行?只需查询开始和结束时间。如果结果>0,则输出错误消息,否则,插入。

我假定这将在插入或更新前触发期间发生

您可能希望查询现有表中的日期重叠,但这将导致一个突变触发器错误

您可以通过使用PRAGMA autonomy_事务生成新线程来解决这个问题

或者-您可以将每个日期范围保存在辅助表中,并使用该表在每次插入时查询。。。类似以下内容(未编译)


假设您的表是tab1,开始日期是stdate,结束日期是endate 另外,让新开始日期和新结束日期位于PLSQL变量v_stdate和v_endate中

所以你的插入可以是

insert into tab1 (stdate,endate)
select v_stdate,v_endate  from dual
where not exists(
select 'overlap' from tab1 t1
where v_stdate between(t1.stdate and nvl(t1.endate,v_endate) 
or   v_endate between(t1.stdate and nvl(t1.endate,v_endate)

)
由于并发问题,这个问题的解决方案有点复杂。在您的例子中,您正在计划一个事件(或一个资源),所以我假设您有一个保存资源的表(比如客户机)。在为客户机添加另一个计划(或事件)之前,应锁定特定的客户机记录,如

select client_id from Clients where client_id=p_client_id for update;

然后,您可以验证是否存在重叠,并插入新的计划和提交。此时,锁将被释放。任何不使用序列化对象的解决方案都可能由于并发问题而存在缺陷。您可以在PLSQL或插入后触发器中执行此操作。但锁定实际资源是绝对必要的录制。

两个链接可让您享受阅读乐趣:-


实际上,这是一个问题。只需发布您所讨论的表的结构即可。Oracle PL/SQL是结构化查询语言SQL的扩展。试着用集合操作而不是程序步骤来思考。您需要查询满足特定条件的任何行,而不是“检查每一行”。我需要一个循环或类似的smth来验证表中的每一行,即date_hour_I和date_hour_e给定的时间间隔与其余行给定的其他时间间隔不相交。还有一个规范…每行的日期对应于一个客户和一个在给定时间间隔内为客户理发的员工…我不想让引入一个新的行,如果对于同一个客户和员工,新的时间间隔与同一客户机和员工的其他时间间隔相交…我希望我说得很清楚…并发性问题可能会破坏此解决方案。如果select和insert语句之间发生另一个insert(例如,其他用户)并且该insert有重叠,该怎么办。然后,我们所有扫描表以查找重叠的解决方案都将失败。上面的触发器不会有并发问题,因为它发生在触发器中。RDBMS将具有驱动查询的读取一致性视图,插入将按顺序进行。读取一致性视图不会阻止其他会话插入/更新。读取一致性仅在需要时提供数据“历史”视图。
select client_id from Clients where client_id=p_client_id for update;