2010-05-24 73 views
0

我必须在Oracle/PLSQL中创建一个进程。我必须验证从我创建的新行开始的start_date和end_date之间的时间间隔不能与其他行的start_dates和end_dates相交。确保Oracle行代表一个独特的时间范围

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

我不知道如何在Oracle/PLSQL中制作重复的指令,如果你能帮助我,我将不胜感激。

我需要一个循环或像这样的smth来验证我的表中的每一行,由date_hour_i和date_hour_e给出的时间间隔不会与其他行给出的其他时间间隔相交。还有一个规范......每行的日期对应于一个客户端和一个员工,在给定的时间间隔内对客户端进行剪发......并且我想以某种方式不让引入新行同一个客户(或其他客户)和员工,新的时间间隔与其他客户和员工的时间间隔相交......我希望我自己清楚......

+0

其实,这是* *的问题。只需发布您所谈论的表格的结构即可。 – eKek0 2010-05-24 19:52:12

+0

Oracle PL/SQL是SQL(结构化查询语言)的扩展。尝试以集合操作而不是程序步骤来思考。而不是“检查每一行”,您需要查询符合某些条件的任何行。 – 2010-05-25 05:15:09

回答

0

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

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; 
/
+0

我需要一个循环或像这样的smth来验证我的表中的每一行,由date_hour_i和date_hour_e给出的时间间隔不会与其他行给出的其他时间间隔相交。还有一个规范......每行的日期对应于一个客户端和一个员工,在给定的时间间隔内对客户端进行剪发......并且我想以某种方式不让引入新行同一个客户和员工,新的时间间隔与相同的客户和员工的其他时间间隔相交......我希望我自己清楚...... – 2010-05-24 20:07:22

+1

同样的并发问题可能会使这种解决方案出现缺陷。如果另一个插入说某个其他用户)发生在select和insert语句之间,并且该插入有重叠。然后,我们所有的扫描表重叠的解决方案将失败。 – josephj1989 2010-05-24 20:39:08

+0

上面的触发器不会产生并发问题 - 因为它发生在触发器中。 RDBMS将具有驱动查询的读取一致视图,并且插入将顺序发生。 – Randy 2010-05-25 14:12:51

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; 

然后你就可以验证有没有重叠,并插入新的时间表和commit.At这一点上,锁将不使用一个序列化对象绑定到是有缺陷的,由于并发问题released.Any解决方案。你可以在你的PLSQL或after插入触发器中完成它,但绝对必须锁定实际的资源记录。