Database/SQL

[Oracle] MyBatis Insert Foreach 대용량 데이터 처리

헹창 2021. 12. 6.
반응형

[Oracle] MyBatis Insert Foreach 대용량 데이터 처리

 

 

oracle mybatis foreach insert

 

[MyBatis] List 파라메터 foreach 사용 (INSERT, DELETE, MERGE, UPDATE) - Oracle

[MyBatis] List 파라메터 foreach 사용 (INSERT, DELETE, MERGE, UPDATE) - Oracle foreach문은 사용할 때마다 사용되는 위치도 속성도 어려워서 더이상 헷갈리지 않기 위해 남겨본다 :-) ! MySQL foreach 사용방..

haenny.tistory.com

 

 

여지껏 Oracle Insert Foreach문이라고 하면 기존에 구현했던 INSERT ALL INTO TABLE 방식을 고집해왔다.

상황에 따라 쿼리를 바꿀줄도 알아야하는데 말이다.

 

DB에 저장되어있는 특정 데이터를 기준으로 여러 코드 값으로 복사하려는 로직에서 시작되었다.

 

특정 데이터는 대략 60개의 데이터였고, 코드 컬럼을 64가지의 코드값으로 각각 60개씩 INSERT 하려니 메모리 오류가 났다.

 

(ORA-00600) - Internal Error Exception

 

 

당연히 INSERT ALL로 INTO TABLE 문만 64 * 60 개가되는 쿼리문을 FOREACH로 돌리려하니 에러가 날 수 밖에..

 


 

기존 쿼리문

1. 특정 쿼리문 조회 = alcrList

2. 코드 컬럼 (DYWK_CLSS, TERM_CLSS) = dywkArray, termArray [String Array]

 

<foreach collection="alcrList" item="item" open="INSERT ALL" close="SELECT * FROM SYS.DUAL;" separator=" "> 
	<foreach collection="dywkArray" item="dywkItem" open="" close="" separator=" ">
		<foreach collection="termArray" item="termItem" open="" close="" separator=" ">
			INTO G_OP_ALCR_TIME ( 
				  MOROUTE_ID
				, TERM_CLSS
				, DYWK_CLSS
				, ALCR_SQNO
				, DPRTR_TIME
				, ROUTE_ID
				, STPT_PNT_ID
				, EDPNT_PNT_ID
				, LIST_X_CRDN
				, LIST_Y_CRDN
				, VHCL_SQNO
				, CRET_DTM
			) VALUES ( 
				  #{item.morouteId} 
				, #{termItem}
				, #{dywkItem}
				, #{item.alcrSqno}
				, #{item.dprtrTime}
				, #{item.routeId}
				, #{item.stptBstaId}
				, #{item.edpntBstaId}
				, #{item.listXCrdn}
				, #{item.listYCrdn}
				, #{item.vhclSqno}
				, SYSDATE
			)
		</foreach>
	</foreach>
</foreach>

 

 

 

수정 쿼리문

INSERT ALL할 필요없이 INSERT INTO 문 하나로 사용

CROSS JOIN을 활용

INSERT INTO  G_OP_ALCR_TIME ( 
	MOROUTE_ID
	, TERM_CLSS
	, DYWK_CLSS
	, ALCR_SQNO
	, DPRTR_TIME
	, ROUTE_ID
	, STPT_PNT_ID
	, EDPNT_PNT_ID
	, LIST_X_CRDN
	, LIST_Y_CRDN
	, VHCL_SQNO
	, CRET_DTM
)
SELECT MOROUTE_ID
 	 , TERM_CLSS
	 , DYWK_CLSS
	 , ALCR_SQNO
	 , DPRTR_TIME
	 , ROUTE_ID
	 , STPT_PNT_ID
	 , EDPNT_PNT_ID
	 , LIST_X_CRDN
	 , LIST_Y_CRDN
	 , VHCL_SQNO
	 , SYSDATE AS CRET_DTM
  FROM (
  		// 특정 쿼리 조회 부분
		SELECT MOROUTE_ID
			 , ALCR_SQNO
			 , DPRTR_TIME
			 , ROUTE_ID
			 , STPT_PNT_ID
			 , EDPNT_PNT_ID
			 , LIST_X_CRDN
			 , LIST_Y_CRDN
			 , VHCL_SQNO
		  FROM G_OP_ALCR_TIME 
		 WHERE MOROUTE_ID = #{morouteId} AND DYWK_CLSS = #{dywkClss} AND TERM_CLSS = #{termClss}
) A CROSS JOIN 
// 코드 데이터 FOREACH 하여 CROSS JOIN
<foreach collection="dyTrmList" item="item" open="(" close=") B" separator="UNION ALL">
	SELECT #{item.term} TERM_CLSS, #{item.dywk} DYWK_CLSS FROM DUAL
</foreach>

 

728x90
반응형

댓글

추천 글