PL / SQL触发器

时间:2013-10-14 22:15:56

标签: sql plsql

我正在尝试制作图书馆信息系统。我有一个名为Borrower(borrower_id: number, name: varchar2(30), status: varchar2(20))的表。 'status'可以是'student''faculty'

我有一个限制,即在任何时间点都可以向学生发放最多2本书,并向教师发放3本书。如何使用触发器实现它?

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

2 个答案:

答案 0 :(得分:0)

我希望你能借用借书人表来计算借书数量,并在借阅书籍和退还书籍时通过触发器对其进行修改。据推测,你也有一张桌子可以让用户借用这些书籍,触发器也可以放在那里。

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

答案 1 :(得分: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;