2010-05-24 30 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插入觸發器中完成它,但絕對必須鎖定實際的資源記錄。