복붙노트

[SQL] 표 트리거 / 함수 (2.5 이하로 떨어지는 평균 등급을 정지)를 볼 수있다 돌연변이

SQL

표 트리거 / 함수 (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'

어떤 충고? 나는 오라클을 사용하고 있습니다.

해결법

  1. ==============================

    1.난 당신이 아니라 트리거 후보다는 전에 트리거로이를 다시 작성하여이 문제를 해결할 수 있다고 생각합니다. 그러나,이 삽입 및 삭제에 대한 복잡 조금있을 수 있습니다. 아이디어는 다음과 같습니다

    난 당신이 아니라 트리거 후보다는 전에 트리거로이를 다시 작성하여이 문제를 해결할 수 있다고 생각합니다. 그러나,이 삽입 및 삭제에 대한 복잡 조금있을 수 있습니다. 아이디어는 다음과 같습니다

    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;  
    
  2. ==============================

    2.DECLARE 안쪽이 문을 사용하여, 그것을 작동합니다.

    DECLARE 안쪽이 문을 사용하여, 그것을 작동합니다.

    pragma autonomous_transaction;
    
  3. ==============================

    3.먼저 테이블 오류 및 화합물 트리거를 돌연변이, 트리거에 대해 읽어해야합니다 http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#LNPLS2005

    먼저 테이블 오류 및 화합물 트리거를 돌연변이, 트리거에 대해 읽어해야합니다 http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#LNPLS2005

    트리거는 UPDATE 또는 INSERT 또는 삭제 한 후입니다. 당신이 UPDATE 또는 INSERT OR이 테이블에 DELETE 문을 실행하면 수단은, 트리거가 실행됩니다. 하지만 당신은 COMPL 당신의 트리거 안에 다시 같은 테이블을 업데이트하려고합니다. 잘못된. 당신이 오류가 발생하는 이유입니다. 당신은 트리거에 발사되어 동일한 테이블을 수정할 수 없습니다. 트리거의 목적은 테이블이 업데이트를 삽입하거나 귀하의 경우 삭제 될 때 자동으로 발사하는 것입니다. 당신이 필요한 것은 약간의 절차가 아닌 트리거입니다.

  4. ==============================

    4.저도 같은 문제를 가지고 나는 당신이 할 경우 당신은 /이 문제를 얻을 수 있습니다 당신에 방아쇠를 넣어 같은 테이블에서 선택한 것으로 나타났습니다. 당신은 각 행에 대해 제거 할 수 있습니다 계산을 수행하는 새로운 (가능한 경우) 다음 업데이트합니다 또는에서 데이터를 사용합니다.

    저도 같은 문제를 가지고 나는 당신이 할 경우 당신은 /이 문제를 얻을 수 있습니다 당신에 방아쇠를 넣어 같은 테이블에서 선택한 것으로 나타났습니다. 당신은 각 행에 대해 제거 할 수 있습니다 계산을 수행하는 새로운 (가능한 경우) 다음 업데이트합니다 또는에서 데이터를 사용합니다.

    귀하의 경우는 학기 당 avg_grade을 별도의 테이블을 사용하는 것이 더 의미가됩니다.

  5. ==============================

    5.심지어 우리는 우리의 프로젝트에 같은 문제를 만난다. 그러나 몇 오라클 포럼에서 검색 한 후, 우리는 솔루션 아래를 발견했다.

    심지어 우리는 우리의 프로젝트에 같은 문제를 만난다. 그러나 몇 오라클 포럼에서 검색 한 후, 우리는 솔루션 아래를 발견했다.

    1) 저장 행 레벨 트리거의 팻 같은 임시 테이블에있는 올드 / 뉴 열 데이터. 2) 문장 레벨 트리거를 작성하고 1 단계에서 저장 한 데이터를 사용합니다.

    이것은 내가 생각하는 문제를 해결합니다.

  6. ==============================

    6.다른 테이블 (TABLE_ADDRESS)에 가입하여 다른 데이터를 검색합니다. 여기 내 솔루션입니다.

    다른 테이블 (TABLE_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;
        /
    
  7. from https://stackoverflow.com/questions/16182089/table-is-mutating-trigger-function-may-not-see-it-stopping-an-average-grade-fr by cc-by-sa and MIT license