删除变异表上的SQL触发器

时间:2017-12-03 18:08:26

标签: sql oracle

我必须为学校做一个项目,我遇到了一个问题。我创建了以下表格:Flights(flight_id,from,to,distance,departure_time,arrival_time,plane_id);平面(plane_id,plane_name,范围);认证(employee_id,plane_id);员工(employee_id,employee_name,薪水)。

在航班中,flight_id是PK,而plane_id是FK引用的平面(plane_id);在Planes中,planes_id是PK,在Employees中employee_id是PK,在认证中plane_id是FK引用Planes(plane_id),emloyee_id是FK referencig Employees(employee_id)(对于作为飞行员的每个员工,我们知道他能用什么样的飞机飞)。

我的问题是我必须创建一个触发器,以确保如果一个平面的范围与至少3个航班的距离兼容,则无法删除该平面。这是我写的代码:

CREATE OR REPLACE TRIGGER planes_del_trigg
        BEFORE DELETE ON planes FOR EACH ROW
    DECLARE 
        CURSOR dist_cur IS
            SELECT distance
            FROM flights;
        v_dist flights.distance%TYPE;
        v_counter NUMBER(3);
    BEGIN
        OPEN dist_cur;
        LOOP
            FETCH dist_cur INTO v_dist;
            IF v_dist <= :OLD.range THEN
                v_counter := v_counter + 1;
            END IF;
            EXIT WHEN dist_cur%NOTFOUND;
        END LOOP;
        CLOSE dist_cur;
        IF v_counter >= 3 THEN
            RAISE_APPLICATION_ERROR(-20501, 'This plane cannot be deleted!');
        END IF;
    END planes_del_trigg;

然而,当我想测试它时,我得到一个错误,表明Flights表正在变异。我相信这是因为我想从Planes表中删除一些东西,而来自Flights的plane_id是FK引用平面(plane_id)(我在ON DELETE CASCADE中添加了约束)。我怎么能解决这个问题?

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

尝试在触发器中使用PRAGMA AUTONOMOUS_TRANSACTION。

Oracle doc:https://docs.oracle.com/cd/B14117_01/appdev.101/b10807/13_elems002.htm

    CREATE OR REPLACE TRIGGER planes_del_trigg
            BEFORE DELETE ON planes
        DECLARE 
            CURSOR dist_cur IS
                SELECT distance
                FROM flights;
            v_dist flights.distance%TYPE;
            v_counter NUMBER(3);

 PRAGMA AUTONOMOUS_TRANSACTION;
        BEGIN
            OPEN dist_cur;
            LOOP
                FETCH dist_cur INTO v_dist;
                IF v_dist <= :OLD.range THEN
                    v_counter := v_counter + 1;
                END IF;
                EXIT WHEN dist_cur%NOTFOUND;
            END LOOP;
            CLOSE dist_cur;
            IF v_counter >= 3 THEN
                RAISE_APPLICATION_ERROR(-20501, 'This plane cannot be deleted!');
            END IF;
        END planes_del_trigg;