0

我正在尝试制作图书馆信息系统。我有一张桌子叫Borrower(borrower_id: number, name: varchar2(30), status: varchar2(20)). 'status'可以是'student''faculty'

我有一个限制,即在任何时候最多可以向学生发行 2 本书,向教职员工发行 3 本书。如何使用触发器实现它?

  1. 这是一个家庭作业问题。但我努力想出一些逻辑。我是 SQL 新手,所以这对你来说可能很容易,但对我来说并不容易。
  2. 我是 stackexchange 的新手,如果我违反了一些规则/惯例,我很抱歉。
4

2 回答 2

0

我希望您会在借书人表上维护借书数量的计数,并在借书和归还书时通过触发器对其进行修改。大概你也有一张用户借书的桌子,触发器会放在那个镜头上。

如果借阅书籍的数量超过 2,则对 books_borrowed 列的约束可能会引发错误。

于 2013-10-14T22:19:16.983 回答
0

这是一个很老的问题,但我发现它非常有用,因为我也是 PL/SQL 初学者。有两种方法可以解决该问题,您要使用的方法取决于 Oracle DB 版本。

  1. 对于旧版本,请结合使用触发器和包,如下所示。
CREATE OR REPLACE TRIGGER trg_borrower 
    BEFORE INSERT OR UPDATE ON borrower 
    FOR EACH ROW
DECLARE

    v_count NUMBER := 0;
BEGIN
    v_count := borrower_pkg.count_rows(:NEW.borrower_id, :NEW.name, :NEW.status);

    IF :NEW.status = 'student' AND v_count = 2 THEN
        RAISE_APPLICATION_ERROR(-20000, 'Error - student');

    ELSIF :NEW.status = 'faculty' AND v_count = 3 THEN
        RAISE_APPLICATION_ERROR(-20001, 'Error - faculty');

    END IF;

END;
/
CREATE OR REPLACE PACKAGE borrower_pkg AS
    FUNCTION count_rows(p_id     IN borrower.borrower_id%TYPE,
                        p_name   IN borrower.NAME%TYPE,
                        p_status IN borrower.status%TYPE) RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY borrower_pkg AS

  FUNCTION count_rows(p_id     IN borrower.borrower_id%TYPE,
                        p_name   IN borrower.NAME%TYPE,
                        p_status IN borrower.status%TYPE) RETURN NUMBER AS

    v_count NUMBER := 0;

  BEGIN
    SELECT COUNT(*) INTO v_count
        FROM borrower
    WHERE borrower_id = p_id AND NAME = p_name AND status = p_status;

    RETURN v_count;
  END count_rows;

END borrower_pkg;
/
  1. 对于 Oracle 10g 及更高版本,您可以使用复合触发器。
CREATE OR REPLACE TRIGGER trg_borrower_comp 
    FOR INSERT OR UPDATE ON borrower
    COMPOUND TRIGGER

    CURSOR c_borrower IS 
        SELECT b1.borrower_id
            FROM borrower b1
        WHERE EXISTS (SELECT 'x' 
                        FROM borrower b2
                      WHERE b2.status = 'student' AND b1.borrower_id =  b2.borrower_id 
                        GROUP BY borrower_id HAVING COUNT(*) = 2)
            OR 
              EXISTS (SELECT 'x'
                        FROM borrower b3
                      WHERE status = 'faculty'AND b1.borrower_id =  b3.borrower_id
                        GROUP BY borrower_id HAVING COUNT(*) = 3);

    TYPE t_borrower_count IS TABLE OF borrower.borrower_id%type; 
    v_borrower_count t_borrower_count;

    BEFORE STATEMENT IS 
    BEGIN

        OPEN c_borrower;
        FETCH c_borrower BULK COLLECT INTO v_borrower_count;
        CLOSE c_borrower;

    END BEFORE STATEMENT;

    BEFORE EACH ROW IS
    BEGIN
        IF :NEW.borrower_id MEMBER OF v_borrower_count THEN
            RAISE_APPLICATION_ERROR(-20000, 'Error - ' || :NEW.status);
        END IF;
    END BEFORE EACH ROW;

END;
于 2019-12-13T10:09:55.377 回答