2013-10-15 24 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

感谢这样一个详细的解释! –