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

时间:2010-05-24 19:48:27

标签: oracle plsql check-constraints

我必须在Oracle / PLSQL中创建一个进程。我必须验证我创建的新行的start_date和end_date之间的时间间隔不得与其他行的其他start_dates和end_dates相交。

现在我需要检查每一行是否存在该条件,如果它不对应,重复的指令应该停止,之后显示消息,例如“给定的时间间隔不正确”

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

我需要一个像这样的循环或smth来验证我的表中的每一行,date_hour_i和date_hour_e给出的时间间隔与其余行给出的其他时间间隔不相交。还有一个规范....每行的日期对应一个客户端和一个员工,在给定的时间间隔内对客户端执行理发....我想不知道如果为了不引入新行同一客户(或其他客户)和员工,新的时间间隔与其他客户和员工的其他时间间隔相交......我希望自己明白......

4 个答案:

答案 0 :(得分:1)

两个链接为您的阅读乐趣: -

Time intervals with no overlaps

Avoiding overlap values...

答案 1 :(得分:0)

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

答案 2 :(得分:0)

我认为这将是在BEFORE INSERT或UPDATE触发期间。

您需要查询现有表格中的日期重叠 - 但这会产生变异的触发错误。

您可以使用PRAGMA AUTONOMOUS_TRANSACTION来生成新线程。

交替 - 您可以将每个日期范围保存在辅助表中,并使用它来查询每个插入...类似于以下内容(未编译)

CREATE OR REPLACE TRIGGER mytrigger
BEFORE INSERT OR UPDATE ON mytable FOR EACH ROW
DECLARE 
    cnt number;
BEGIN 
    SELECT count(*) into cnt
    FROM reserved_date_range                
    WHERE :new.begin_date BETWEEN begin_dt and end_dt

    if ( cnt > 0 ) then
        raise_application_error(-20000,'Overlapping date ranges');
    else
        insert into reserved_date_range( begin_dt, end_dt ) 
        values ( :new.begin_date, :new.end_date );
    end if;
End;
/

答案 3 :(得分:0)

假设您的表格为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或After Insert触发器中。但是绝对必须锁定实际的资源记录。