我正在尝试使用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 :(得分: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
答案 1 :(得分:0)
这太丑了我不敢相信你会被要求做这样的事情。触发器是实现业务逻辑的最糟糕方式之一。当面对多个用户时,他们经常会完全失败。它们也难以调试,因为它们具有难以预料的副作用。
在您的示例中,例如,如果两个人同时插入会发生什么? (提示:他们不会看到彼此的修改,直到他们都提交,生成损坏数据的好方法:)
此外,正如您可能知道的那样,您无法在行级触发器中引用表的其他行(这将引发变异错误)。
如果说,在您的情况下,您可以使用Borrower
中的额外列来记录借阅的图书数量。您必须确保触发器正确更新此值。这也将解决多用户问题,因为您知道只有一个会话可以同时更新单个行。因此,只有一个人可以同时更新借款人的数量。
这应该可以帮助您使用插入触发器(您还需要一个删除触发器,并且如果有人更新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)。