2013-10-15 35 views
0

我正在嘗試使用PL/SQL製作庫信息娛樂系統。在你們任何人推測之前,是的,這是一項家庭作業,但我努力嘗試並在努力嘗試之後在這裏提出問題。PL/SQL觸發器庫信息娛樂系統

基本上我有幾張表,其中有兩張是: Issue(Bookid, borrowerid, issuedate, returndate) Borrower(borrowerid, name, status)

Borrower表中的狀態可以是'student' or 'faculty'。我必須使用觸發器實施限制,根據student,我可以在任何時間點和任何時間點根據faculty發行2本書,3本書。

我完全是PL/SQL的新手。這可能很容易,我有一個如何去做的想法。這是我能做的最好的。請幫我找到設計/編譯器錯誤。

CREATE OR REPLACE TRIGGER trg_maxbooks 
AFTER INSERT ON ISSUE 
FOR EACH ROW 
DECLARE 
    BORROWERCOUNT INTEGER; 
    SORF VARCHAR2(20); 
BEGIN 
    SELECT COUNT(*) INTO BORROWERCOUNT 
    FROM ISSUE 
    WHERE BORROWER_ID = :NEW.BORROWER_ID; 

    SELECT STATUS INTO SORF 
    FROM BORROWER 
    WHERE BORROWER_ID = :NEW.BORROWER_ID; 

    IF ((BORROWERCOUNT=2 AND SORF='STUDENT') 
     OR (BORROWERCOUNT=3 AND SORF='FACULTY')) THEN 
     ROLLBACK TRANSACTION; 
    END IF; 
END; 

回答

0

嘗試是這樣的:

CREATE OR REPLACE TRIGGER TRG_MAXBOOKS 
    BEFORE INSERT 
    ON ISSUE 
    FOR EACH ROW 
BEGIN 
    IF (:NEW.BORROWERCOUNT > 2 
     AND :NEW.SORF = 'STUDENT') 
     OR (:NEW.BORROWERCOUNT > 3 
      AND :NEW.SORF = 'FACULTY') 
    THEN 
     RAISE_APPLICATION_ERROR (
          -20001, 
          'Cannot issue beyond the limit, retry as per the limit'); 
    END IF; 
END; 
/

不應該有一個觸發器內提交或回滾。邏輯異常相當於ROLLBACK

+0

非常感謝您的努力。只有一個問題 - 在任何表格中都沒有列爲「borrowercount」。我懷疑這是否會奏效。 –

+0

你應該採取計數,並將其作爲參數:)這不是一個簡單的答案,但只有一個模型 – SriniV

0

這是如此醜陋我不敢相信你被要求做這樣的事情。觸發器是實現業務邏輯的最糟糕的方式之一。遇到多個用戶時,他們往往會完全失敗。他們也很難調試,因爲他們很難預測副作用。

在你的例子中,如果兩個人同時插入會發生什麼? (提示:他們不會看到對方的修改,直到他們都承諾,很好的方式來產生損壞的數據:)

此外,正如你可能知道的,你不能引用行中的表的其他行級別觸發器(這會引發突變錯誤)。

這就是說,在你的情況下,你可以使用額外的列Borrower來記錄借用的書籍數量。您必須確保觸發器正確更新此值。這也將處理多用戶問題,因爲您知道只有一個會話可以同時更新單個行。所以只有一個人可以同時更新借款人的數量。

這會幫助你用INSERT觸發器(你還需要一個刪除觸發器,併爲安全起見,以防有人更新觸發更新Issue.borrowerid):

CREATE OR REPLACE TRIGGER issue_borrower_trg 
    AFTER INSERT ON issue 
    FOR EACH ROW 
DECLARE 
    l_total_borrowed NUMBER; 
    l_status borrower.status%type; 
BEGIN 
    SELECT nvl(total_borrowed, 0) + 1, status 
    INTO l_total_borrowed, l_status 
    FROM borrower 
    WHERE borrower_id = :new.borrower_id 
     FOR UPDATE; 
    -- business rule 
    IF l_status = 'student' and l_total_borrowed >= 3 
     /* OR faculty */ THEN 
     raise_application_error(-20001, 'limit reached!'); 
    END IF; 
    UPDATE borrower 
     SET total_borrowed = l_total_borrowed 
    WHERE borrower_id = :new.borrower_id; 
END; 

更新:上述方法甚至不適用於您的情況,因爲您在issue表中記錄了發放日期/返回日期,因此借用的書籍數量不會隨着時間的推移而變化。在這種情況下,我會使用表級POST-DML觸發器。每個DML驗證表中的每一行都驗證了您的業務規則(但它不會很好地進行縮放,對於可縮放的解決方案,請參閱this post by Tom Kyte)。

+0

感謝這樣一個詳細的解釋! –