runtime시 에러가 발행합니다.(수정중에는 테이블에 접근할 수 없습니다) 0 4 3,094

by 조신부리 [PL/SQL] [2018.12.06 16:32:29]


CREATE OR REPLACE TRIGGER HOST_SCHOOL.MDAPPLCNT_TRG
AFTER INSERT OR UPDATE  OR DELETE ON HOST_SCHOOL.MDAPPLCNT FOR EACH ROW
DECLARE 

	v_APPLCNT_ID			HOST_SCHOOL.MDAPPLCNT.APPLCNT_ID 		%TYPE ; 			
	v_APPLCNT_NM 			HOST_SCHOOL.MDAPPLCNT.APPLCNT_NM 		%TYPE ; 	
	v_CONFM_CODE 			HOST_SCHOOL.MDAPPLCNT.CONFM_CODE 		%TYPE ; 	
	v_FRST_REGISTER_ID 	    HOST_SCHOOL.MDAPPLCNT.FRST_REGISTER_ID 	%TYPE ; 	
	v_FRST_REGIST_PNTTM 	HOST_SCHOOL.MDAPPLCNT.FRST_REGIST_PNTTM %TYPE ; 	
	v_LAST_UPDT_PNTTM 	    HOST_SCHOOL.MDAPPLCNT.LAST_UPDT_PNTTM 	%TYPE ; 	
	v_LAST_UPDUSR_ID 		HOST_SCHOOL.MDAPPLCNT.LAST_UPDUSR_ID 	%TYPE ; 	
	v_REQST_DY 			    HOST_SCHOOL.MDAPPLCNT.REQST_DY 			%TYPE ; 	
	v_REQST_ID 			    HOST_SCHOOL.MDAPPLCNT.REQST_ID 			%TYPE ; 	
	v_USER_SEQ 			    HOST_SCHOOL.MDAPPLCNT.USER_SEQ 			%TYPE ; 	
	v_USE_AT 				HOST_SCHOOL.MDAPPLCNT.USE_AT 		    %TYPE ; 	
	v_NEW_CONFM_CODE 		HOST_SCHOOL.MDAPPLCNT.CONFM_CODE 		%TYPE ; 	
 
CURSOR select_applicant_source IS
    SELECT
		 a.APPLCNT_ID							
		, a.APPLCNT_NM 			        
		, a.CONFM_CODE 			        
		, a.FRST_REGISTER_ID 	        
		, a.FRST_REGIST_PNTTM 	        
		, a.LAST_UPDT_PNTTM 	        
		, a.LAST_UPDUSR_ID 		        
		, a.REQST_DY 			        
		, a.REQST_ID 			        
		, a.USER_SEQ 			        
		, a.USE_AT 		                
	    , (CASE WHEN  ROW_NUMBER() OVER(ORDER BY a.REQST_DY ) <= r.PSNCPA THEN 'ACS002' ELSE NULL END)   AS NEW_CONFM_CODE 
    FROM	HOST_SCHOOL.MDREQSTINFO r
    	  , HOST_SCHOOL.MDAPPLCNT a	
    WHERE 	r.REQST_ID 			= a.REQST_ID
    AND 	r.CONFM_MTHD_CODE	= 'REC001'
    AND 	a.USE_AT			= 'Y'
    AND 	r.REQST_ID			=  :new.REQST_ID
    ;	 
	 
BEGIN
	
    OPEN select_applicant_source ;

    LOOP FETCH select_applicant_source INTO
				 v_APPLCNT_ID			
				, v_APPLCNT_NM 			
				, v_CONFM_CODE 			
				, v_FRST_REGISTER_ID 	    
				, v_FRST_REGIST_PNTTM 	
				, v_LAST_UPDT_PNTTM 	    
				, v_LAST_UPDUSR_ID 		
				, v_REQST_DY 			    
				, v_REQST_ID 			    
				, v_USER_SEQ 			    
				, v_USE_AT 
				, v_NEW_CONFM_CODE	;
        EXIT WHEN select_applicant_source%NOTFOUND ;

		UPDATE  HOST_SCHOOL.MDAPPLCNT
		SET
		    CONFM_CODE             	=  v_NEW_CONFM_CODE
		    ,LAST_UPDUSR_ID			= 'trg'
		WHERE 	APPLCNT_ID          =  v_APPLCNT_ID
		AND		REQST_ID			=  v_REQST_ID
		;
		
		COMMIT;	
	
    END LOOP ;

    EXCEPTION
            WHEN OTHERS THEN
                RAISE_APPLICATION_ERROR(-20002,v_APPLCNT_ID || '@@@@' || v_NEW_CONFM_CODE ||'@@@@:' || SQLERRM);

END;

안녕하세요.

티베로6에서 트리거를 작성했습니다.

자신의테이블에 입력,수정,삭제가 발생하면 자신의테이블의 기존데이터를 업데이트 시키려고합니다.

컴파일은 됐는데 실행시 아래와 같은 에러가 발생합니다.

JDBC-20002:345@@@@@@@@:TBR-15095: Trigger/function cannot access table 'MDAPPLCNT' while it is being modified

감사합니다

by 신이만든지기 [2018.12.06 16:56:28]

업데이트 트리거가 걸려있는 테이블(HOST_SCHOOL.MDAPPLCNT)을 트리거 안에서 업데이트를 시도하셔서 그런 것 같네요.

1. MDAPPLCNT 업데이트 발생

2. MDAPPLCNT 업데이트 트리거 실행

3. 트리거 내에서 MDAPPLCNT 업데이트 시도

4. MDAPPLCNT 트리거 실행시도 -> 에러발생


by 조신부리 [2018.12.06 17:59:27]

답변감사합니다.

티베로는 해당테이블을 view로 만들어서 instead of trigger로 작업하라고 하네요.

좀 더 익숙한 프로시져로 변경해서 소스에서 호출해주는걸로 변경완료했습니다.

복수 채택이 되지 않네요.....덕분에 배워갑니다. 


by 마농 [2018.12.06 16:58:25]

업데이트 중인 테이블에 트리거를 걸었는데
트리거 안에서 업데이트를 치면
트리거가 무한루프를 돌겠지요.
그래서 무한루프 방지하기 위해 에러가 나는 것입니다.
행트리거 하나만 가지고 해결이 안됩니다.
문장 트리거와 행트리거를 적절하게 섞어서 구현하셔야 합니다.
http://gurubee.net/article/53504
다음과 같은 절차로 구현되어야 합니다.
1. 변경되는 reqst_id 를 담을 테이블타입의 패키지 변수 생성
2. Before 문장트리거에서 변수 초기화
3. 행 트리거에서 변수에 reqst_id 를 저장
4. After 문장트리거에서 해당 변수 루프 돌려가면서 해당 로직 수행
오라클 11G 부터는 compound trigger(복합 트리거)가 가능하여 트리거 여러개 작성 안해도 됩니다.
하나의 트리거 안에서 여러가지 타입의 트리거 구현이 가능합니다.
티베로에서도 위와 같이 구현이 가능한지 확인해 보세요.

하지만 위 복합 트리거 방법은 구현도 복잡하고 까다롭습니다.
트리거 가 아닌 프로그램에서 처리하는 방안은 없을지 고민해 보세요.


by 조신부리 [2018.12.06 17:55:58]

트리거대신 프로시져로 변경 완료했습니다.

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입