2016-06-09 174 views
0

需要你的幫助交叉表數據驗證

我有2個連接的實體:庫讀者(訂戶)和書的問題。讀者可以在因爲破壞圖書館的規定天被鎖定一段時間:

DB logical scheme

我需要補充檢查,以便讀者,誰的鎖定期尚未結束,不能拿一本書在庫(換句話說,Issue.Taken> Subscriber.Lock_Date + Subscriber.Lock_Period)

請幫忙,我該怎麼做?

回答

1

我MTO同意,這樣的驗證應該由應用程序代碼來處理(通過存儲過程)。但是,如果您堅持通過數據庫執行此驗證,那麼以下觸發器將會有所幫助。同樣,我不推薦這種解決方案,最好的方法是使用應用程序邏輯處理它。

CREATE OR REPLACE TRIGGER trg_val_lock_dt 
BEFORE INSERT ON issue 
FOR EACH ROW 
DECLARE 
    v_is_valid CHAR(1); 
BEGIN 

    v_is_valid := 'Y'; 

    SELECT 'N' INTO v_is_valid 
    FROM subscriber s 
    WHERE :NEW.subscr_id = s.subscr_id 
    AND :NEW.taken BETWEEN s.lock_date AND (s.lock_date + lock_period); 

    RAISE_APPLICATION_ERROR(-20001,'The subscriber is locked'); 

EXCEPTION 
    WHEN NO_DATA_FOUND THEN 
     NULL; 
END; 

上述觸發將在問題表中的每個插入之前進行發射。它將檢查所採用的日期是否在鎖定日期和鎖定日期+鎖定週期之間(這將是鎖定結束日期)。如果找到這樣的記錄,那麼它將拋出以下錯誤,並且該行不會被插入。

ORA-20001: The subscriber is locked 
ORA-06512: at "RETAIL_1.TRG_VAL_LOCK_DT", line 12 

如果條件不滿足,則沒有內容,將引發異常,其中觸發器將什麼也不做,行將被插入。

+0

它適用於在表中插入新行,但是當我嘗試返回書籍(或任何其他更新)時,我得到ORA-04091表是變異錯誤。我能繞過這個錯誤還是觸發限制? – JGDger

+0

但觸發器只能在插入時觸發。它在更新上發射嗎? –

+0

是的,錯誤引發更新,我不明白爲什麼 – JGDger

3

這應該在業務邏輯中真正處理,而不是在表級別處理。

但是,你可以使用物化視圖做到這一點:

CREATE TABLE subscriber (
    id   INT PRIMARY KEY, 
    lock_date DATE, 
    lock_period INTERVAL DAY(5) TO SECOND 
); 

CREATE TABLE issue (
    id  INT PRIMARY KEY, 
    subscr_id INT NOT NULL REFERENCES subscriber(id), 
    book_id INT, 
    taken  DATE, 
    returned DATE 
); 

CREATE MATERIALIZED VIEW LOG ON subscriber 
    WITH SEQUENCE, ROWID(id, lock_date, lock_period) 
    INCLUDING NEW VALUES; 

CREATE MATERIALIZED VIEW LOG ON issue 
    WITH SEQUENCE, ROWID(subscr_id, taken) 
    INCLUDING NEW VALUES; 

CREATE MATERIALIZED VIEW subscriber_issue_MV 
    BUILD IMMEDIATE 
    REFRESH FAST ON COMMIT 
    AS SELECT s.id, 
      s.lock_date, 
      s.lock_period, 
      i.taken 
     FROM subscriber s 
      INNER JOIN 
      issue i 
      ON (i.subscr_id = s.id); 

ALTER TABLE subscriber_issue_MV ADD CONSTRAINT subscriber_issue__mv__chk 
    CHECK ( lock_date IS NULL 
     OR lock_period IS NULL 
     OR NOT taken BETWEEN lock_date AND lock_date + lock_period); 
+0

嘗試它,但嘗試創建物化視圖時出現錯誤:ORA 00439 - 功能未啓用:高級複製。這是否意味着由於某種原因我無法創建物化視圖? – JGDger

+0

你可以但是你不能使用日誌或'FAST REFRESH ON COMMIT' ......這意味着它可以工作,但是你必須通過另一種方法保持物化視圖的更新 - 這會使它變得不切實際。 – MT0

+0

正如我在第一行中所說 - 在表級解決這個問題是可能的,但不是最好的解決方案。更好的解決方案是隻允許通過程序(或用於訪問oracle的中間層的業務邏輯)取出書籍,然後包裝檢查用戶沒有被鎖定的所有業務邏輯。 – MT0