这是一个很老的问题,但我发现它非常有用,因为我也是 PL/SQL 初学者。有两种方法可以解决该问题,您要使用的方法取决于 Oracle DB 版本。
- 对于旧版本,请结合使用触发器和包,如下所示。
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;
/
- 对于 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;