이 문서는 MySQL 5.5 버전에서 KingbaseES V8 버전으로 데이터베이스를 마이그레이션하는 과정에서 발생하는 SQL 호환성 문제를 해결하는 방법에 대해 다룹니다. KingbaseES의 MySQL 호환 모드를 사용하더라도 발생하는 특정 SQL 문제에 대한 해결책을 제시합니다.
1. 데이터 내보내기 SQL: COPY
MySQL에서는 SELECT 문의 결과를 지정된 형식의 텍스트 파일로 내보내기 위해 INTO OUTFILE 구문을 사용합니다.
SELECT ... INTO OUTFILE '/path/to/file' FIELDS TERMINATED BY '|' LINES TERMINATED BY '\r\n' FROM ...
KingbaseES V8에서는 이 구문이 COPY 명령으로 변경되었습니다.
COPY (SELECT ...) TO '/path/to/file' WITH (DELIMITER '|')
MyBatis 프레임워크에서 위 기능을 사용할 경우, 동적 SQL 구문 처리에 주의해야 합니다. MyBatis는 #{}와 ${} 두 가지 방식의 파라미터 바인딩을 지원합니다. #{}는 PreparedStatement를 사용하여 SQL Injection을 방지하지만, 동적 테이블명이나 컬럼명처럼 SQL 구조 자체를 변경해야 하는 경우에는 ${}를 사용해야 합니다. KingbaseES의 COPY 명령은 PreparedStatement 문법을 지원하지 않으므로, 모든 파라미터는 ${}를 사용하여 전달해야 합니다. #{}를 사용하면 다음과 같은 오류가 발생할 수 있습니다.
Caused by: com.kingbase8.util.KSQLException: ERROR: parameter $1 does not exist
SQL Injection을 방지하기 위해, 서비스 계층에서 허용된 테이블 목록을 미리 정의하고 이를 검증하는 화이트리스트 방식을 ${}와 함께 사용하는 것을 권장합니다.
Set<String> allowedTables = Set.of("table1", "table2", ...);
if (!allowedTables.contains(param2)) {
throw new IllegalArgumentException("Invalid table name");
}
2. 데이터 가져오기 SQL: LOAD
MySQL과 KingbaseES 모두 파일에서 데이터를 가져오기 위해 LOAD DATA 구문을 사용합니다.
LOAD DATA LOCAL INFILE '/path/to/file' INTO TABLE your_table FIELDS TERMINATED BY '|' LINES TERMINATED BY '\r\n'
MySQL에서 사용하던 LOAD DATA 구문을 KingbaseES로 직접 마이그레이션할 경우, 한글 데이터가 깨지는 현상이 발생할 수 있습니다. 이는 MySQL이 데이터베이스의 기본 문자셋(예: utf8mb4)을 따르는 반면, KingbaseES는 클라이언트의 기본 문자셋(예: UTF8)을 사용하기 때문입니다. 이 문제를 해결하기 위해, LOAD DATA 구문에 CHARACTER SET utf8mb4 옵션을 명시하여 KingbaseES가 MySQL 호환 모드를 사용하도록 지정해야 합니다.
LOAD DATA LOCAL INFILE '/path/to/file' INTO TABLE your_table CHARACTER SET utf8mb4 FIELDS TERMINATED BY '|' LINES TERMINATED BY '\r\n'
3. 자동 증가 행 번호 생성
MySQL에서는 이전 버전에서 사용자 정의 변수를 사용하여 행 번호를 동적으로 생성하는 방식을 사용했습니다.
SET @rownum = 0;
SELECT @rownum := @rownum + 1 AS row_number, ... FROM ...
MySQL 8.0 이상 버전에서는 ROW_NUMBER() OVER (ORDER BY ...)` 윈도우 함수를 통해 더 표준적인 방식으로 행 번호를 생성할 수 있습니다. KingbaseES는 MySQL의 구식 방식은 지원하지 않으며, 윈도우 함수만을 지원합니다. 따라서 MySQL의 구식 행 번호 생성 구문은 KingbaseES에서 지원하는 윈도우 함수 방식으로 수정해야 합니다.
ROW_NUMBER() OVER (ORDER BY some_column) AS row_number