ORA-04091: 테이블이 변경되어 트리거/함수가 볼 수 없습니다 오류는 오라클 데이터베이스에서 트리거 또는 함수가 직접적으로 영향을 받는 테이블을 다시 읽거나 변경하려고 할 때 발생해요! 😭 이는 트리거의 순환 참조나 무한 반복으로 이어질 수 있어 오라클에서 미리 예외로 처리하는 부분이랍니다. (트리거의 재귀 호출)
그리하여 문제를 해결하려면 테이블이 변경이 어디에서 이루어지는지 확인하여 적절한 처리방법이 필요하답니다. 다음을 참고하여 해결해 보세요.
트리거로 인해 복잡한 로직이 순환 참조 및 성능 문제를 일으킬 가능성을 염두에 두어야 합니다.
트리거의 흐름 분석하기
- 트리거가 다른 테이블을 업데이트하거나 동일 테이블을 다시 참조하여 수정하려는 경우를 검토하세요.
- 순환 참조가 발생하지 않도록 트리거의 동작 순서를 명확히 정의합니다.
- 예를 들어, A 테이블의 트리거가 B 테이블을 업데이트하고, B 테이블의 트리거가 다시 A 테이블을 업데이트한다면, 트리거 설계 자체를 재검토해야 합니다.
- 아니면, A 테이블에 대한 데이터 조작시(DML), 트리거에서 다시 A 테이블의 데이터 조작을 시도하려고 할 때에 발생할 수 있어요.
아래에서 몇 가지 예를 들어 볼텐데요, 객체지향에 어긋나는 설계가 될 가능성이 높으므로 추천하지 않습니다! 이러한 트리거나 함수가 정말 필요한지 다시 한 번 점검을 해보세요.
PRAGMA AUTONOMOUS_TRANSACTION 사용하는 방법
- 트리거 안에서 독립적인 트랜잭션을 사용하면 순환 참조를 피할 수 있습니다.
- 그러나 이 방식은 데이터 일관성을 유지하기 어려울 수 있으므로 신중히 사용하세요.
View 및 INSTEAD OF Trigger를 이용하기
- 뷰와 대신 트리거(INSTEAD OF Trigger)를 사용하여 순환 참조를 우회해 봅니다.
- 이 방식은 뷰를 통해 간접적으로 데이터 업데이트를 처리하며 순환 구조를 피하려는 시도예요.
비즈니스 로직 재구성
- 가능하다면, 트리거 대신 프로시저나 애플리케이션 레벨에서의 데이터 처리로 로직을 재구성하세요.
- 트리거는 유지보수가 어렵고 예측 불가능한 동작을 초래할 수 있으므로 복잡한 로직을 트리거에 구현하는 것은 권장하지 않아요.
기타
그외, AFTER 트리거를 BEFORE 로 교체하여, UPDATE 구문을 제외하고 신규값을 변경처리하는 방법도 있어요. 또는 그 반대로 AFTER 트리거를 변경하는 경우도 있다고 하는데요, BEFORE 트리거로 해결하는 방법은 찾을 수 있었는데, 반대의 경우는 없는 것 같네요.
