programing

테이블이 돌연변이 중이므로 트리거/기능이 이를 보지 못할 수 있습니다(평균 기울기가 2.5 미만으로 떨어지는 것을 방지).

kingscode 2023. 7. 20. 22:49
반응형

테이블이 돌연변이 중이므로 트리거/기능이 이를 보지 못할 수 있습니다(평균 기울기가 2.5 미만으로 떨어지는 것을 방지).

문제는 다음과 같습니다.

특정 클래스의 전체 평균 등급이 2.5 이하로 떨어지는 취학 관계의 변경을 방지하는 트리거를 만듭니다.참고: 이 트리거는 특정 학생의 평균 GPA를 처리하기 위한 것이 아니라 특정 클래스에 할당된 모든 등급의 평균 성적을 처리해야 합니다.

스키마는 다음과 같습니다.

Student-schema =(studentnum, name, standing, gpa, major)
Class-schema = (schedulenum, semester, department, classnum, days, time, place, enrollment)
Instructor-schema = (name, department, office)
Teaches-schema = (name, schedulenum, semester)
Taking-schema = (studentnum, schedulenum, semester, grade)

저는 이 방아쇠들 때문에 끔찍한 시간을 보내고 있지만, 이 일을 성공시키기 위한 저의 시도는 다음과 같습니다.

CREATE OR REPLACE TRIGGER stopChange
    AFTER UPDATE OR INSERT OR DELETE ON taking
    REFERENCING OLD AS old
    NEW AS new
    FOR EACH ROW
DECLARE

grd_avg taking.grade%TYPE;

BEGIN
    SELECT AVG(grade)
    INTO grd_avg
    FROM taking
    WHERE studentnum = :new.studentnum
    AND schedulenum = :new.schedulenum
    AND semester = :new.semester;

    IF grd_avg < 2.5 THEN
        UPDATE taking
        SET grade = :old.grade
        WHERE studentnum = :old.studentnum
        AND schedulenum = :old.schedulenum
        AND semester = :old.semester;
    END IF;

END;   
/

튜플을 업데이트하거나 삭제할 때 다음과 같은 오류가 발생하기 때문에 분명히 잘못된 것입니다.

ERROR at line 1:
ORA-04091: table TAKING is mutating, trigger/function may not see it
ORA-06512: at "STOPCHANGE", line 6
ORA-04088: error during execution of trigger 'STOPCHANGE'

조언이 있습니까?오라클을 사용하고 있습니다.

먼저 트리거, 변환 테이블 오류 및 복합 트리거에 대한 내용을 읽어야 합니다. http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#LNPLS2005

트리거는 업데이트 또는 삽입 또는 삭제 후입니다.이 테이블에서 UPDATE 또는 INSERT 또는 DELETE 문을 실행하면 트리거가 실행됩니다.그러나 트리거 내에서 동일한 테이블을 다시 업데이트하려고 하는데, 이는 잘못된 것입니다.이것이 오류가 발생하는 이유입니다.트리거가 실행되는 것과 동일한 테이블은 수정할 수 없습니다.트리거의 목적은 테이블이 업데이트, 삽입 또는 삭제될 때 자동으로 실행되는 것입니다.당신에게 필요한 것은 어떤 절차이지 방아쇠가 아닙니다.

을 이문을사용 안에 하세요.DECLARE,그건 작동할 것이다.

pragma autonomous_transaction;

이것을 애프터 트리거가 아닌 비포 트리거로 다시 작성하면 이 문제를 해결할 수 있다고 생각합니다.그러나 삽입 및 삭제에는 약간 복잡할 수 있습니다.아이디어는 다음과 같습니다.

CREATE OR REPLACE TRIGGER stopChange
    BEFORE UPDATE OR INSERT OR DELETE ON taking
    REFERENCING OLD AS old
    NEW AS new
    FOR EACH ROW
DECLARE

grd_avg taking.grade%TYPE;

BEGIN
    SELECT (SUM(grade) - oldgrade + new.grade) / count(*)
    INTO grd_avg
    FROM taking
    WHERE studentnum = :new.studentnum
    AND schedulenum = :new.schedulenum
    AND semester = :new.semester;

    IF grd_avg < 2.5 THEN
        new.grade = old.grade
    END IF;
END;  

저도 같은 문제가 있었는데 같은 테이블에서 선택을 하면 이 문제가 발생할 수 있다는 것을 알게 되었습니다. 행에 대해 제거하거나 :New의 데이터를 사용하여 계산을 수행한 다음(가능한 경우) 업데이트할 수 있습니다.

당신의 경우 학기당 평균 성적을 내기 위해 별도의 표를 사용하는 것이 더 타당할 것입니다.

심지어 우리 프로젝트에서도 같은 문제가 발생했습니다.그러나 몇 개의 오라클 포럼을 검색한 결과 아래와 같은 솔루션을 발견했습니다.

Old/New Column 데이터를 행 레벨 트리거의 pat로 임시 테이블에 저장합니다. 2) 문 레벨 트리거를 작성하고 1단계에서 저장한 데이터를 사용합니다.

이렇게 하면 제가 생각하는 문제가 해결될 것 같습니다.

다른 테이블에 가입하여 다른 데이터를 검색하려는 경우(TAB)LE_ADDRESS).여기 제 해결책이 있습니다.

 CREATE OR REPLACE TRIGGER TRIGGER_TABLE_ACTIVITIES AFTER  INSERT ON TABLE_NAME
     FOR EACH ROW
    DECLARE 
    V_ADDRESS VARCHAR2(100); 
    BEGIN 

            SELECT A.ADDRESS INTO V_ADDRESS 
            FROM TABLE_ADDRESS A
            WHERE A.ADDRESSID = :NEW.ADDRESSID
            ;
            INSERT INTO TABLE_ACTIVITIES(
                            NAME, ADDRESS)
            VALUES(:NEW.NAME, V_ADDRESS);
    END;
    /

언급URL : https://stackoverflow.com/questions/16182089/table-is-mutating-trigger-function-may-not-see-it-stopping-an-average-grade-fr

반응형