MyBatis XML 기준,
Oracle SQL → PostgreSQL SQL 전환 시
- ✅ 정규식·스크립트로 자동 치환 가능한 것
- ❌ 절대 자동 치환하면 안 되는 것(사람이 재작성해야 하는 것)
을 실무 기준으로 정리한 목록.
1️⃣ 자동 치환 가능한 것 (Script / Regex로 처리 가능)
조건: 의미가 1:1로 대응되고, 결과가 달라질 여지가 거의 없는 것
✅ 1. NULL 처리 함수
| Oracle | PostgreSQL | 비고 |
| NVL(a, b) | COALESCE(a, b) | 의미 동일 |
| NVL2(a, b, c) | CASE WHEN a IS NOT NULL THEN b ELSE c END | 패턴 치환 가능 |
📌 주의
- NVL 안에 서브쿼리/함수 중첩돼 있어도 대부분 안전
✅ 2. 문자열 함수 (단순형)
| Oracle | PostgreSQL |
| SUBSTR(a, b, c) | SUBSTRING(a FROM b FOR c) |
| LENGTH(a) | LENGTH(a) |
| TRIM(a) | TRIM(a) |
| UPPER / LOWER | 동일 |
📌 권장
- SUBSTR → SUBSTRING은 정규식 치환으로 가능
- 단, 인자 순서 바뀌는 것만 주의
✅ 3. 날짜 계산 (단순 산술)
| Oracle | PostgreSQL |
| SYSDATE | now() |
| SYSDATE - 1 | now() - interval '1 day' |
| SYSDATE + 7 | now() + interval '7 days' |
📌 주의
- 컬럼 타입이 date인지 timestamp인지 확인은 필요
- 그래도 자동 치환 대상에 포함 가능
✅ 4. DUAL 제거
-- Oracle
SELECT1FROM DUAL;
-- PostgreSQL
SELECT1;
📌 100% 자동 치환 가능
✅ 5. TO_CHAR / TO_DATE (형식이 명확한 경우)
-- Oracle
TO_CHAR(dt,'YYYYMMDD')
TO_DATE('20240101','YYYYMMDD')
-- PostgreSQL
TO_CHAR(dt,'YYYYMMDD')
TO_DATE('20240101','YYYYMMDD')
📌 함수 이름/포맷 문자열이 동일해서 그대로 유지 가능
(이건 의외로 안 바꿔도 됨)
✅ 6. 문자열 결합 (단순)
a|| b
- PostgreSQL도 || 지원
- 둘 다 문자열(text/varchar)인 경우 자동 치환 불필요
📌 숫자 섞이면 위험 → 그건 ❌ 영역
✅ 7. 기본 집계 함수
| Oracle | PostgreSQL |
| COUNT | 동일 |
| SUM | 동일 |
| MAX / MIN | 동일 |
| AVG | 동일 |
📌 GROUP BY 의미도 동일 → 안전
2️⃣ ❌ 절대 자동 치환하면 안 되는 것 (사람이 책임져야 함)
이 영역은 문법만 맞게 바꿔도 결과가 달라질 수 있음
→ 자동화하면 “조용히 틀린 결과”가 나오는 최악의 구간
❌ 1. ROWNUM / 페이징
-- Oracle
SELECT*
FROM (
SELECT A.*, ROWNUM RN
FROM A
ORDERBY CREATED_ATDESC
)
WHERE RNBETWEEN11AND20;
🚫 자동 치환 금지 이유
- Oracle은 ROWNUM → ORDER BY 순서
- PostgreSQL은 ORDER BY → LIMIT/OFFSET
- 단순 치환하면 조회 결과가 달라짐
👉 반드시 쿼리 의도를 해석해서 재작성
❌ 2. (+) OUTER JOIN
-- Oracle
A.ID= B.A_ID(+)
🚫 자동 치환 금지 이유
- (+) 위치에 따라 LEFT / RIGHT JOIN 의미가 달라짐
- 여러 테이블 얽히면 사람도 헷갈림
👉 JOIN 구조 재작성 필수
❌ 3. DECODE
DECODE(status,'A',1,'B',2,0)
🚫 자동 치환 위험
- CASE WHEN으로 바꾸는 건 가능해 보이지만
- NULL 처리 / default 처리 차이로 결과 어긋나는 경우 잦음
👉 CASE WHEN 직접 작성 + 테스트
❌ 4. MERGE INTO
MERGEINTO ...
🚫 완전 다른 개념
- PostgreSQL은 INSERT ... ON CONFLICT
- 로직 구조 자체가 다름
👉 비즈니스 로직 재작성 대상
❌ 5. 날짜 비교 로직 (TRUNC, 월 계산 등)
TRUNC(sysdate)
TRUNC(order_dt,'MM')
🚫 자동 치환 금지 이유
- PostgreSQL엔 TRUNC(date) 개념 없음
- date_trunc()로 대체 가능하지만 의미가 완전히 같지 않음
👉 업무 기준으로 재정의 필요
❌ 6. 숫자 + 문자열 혼합 연산
'ORD-'|| order_no
🚫 Oracle은 암묵적 형변환 허용
🚫 PostgreSQL은 에러 발생
👉 명시적 캐스팅 필요 (order_no::text)
❌ 7. 서브쿼리 안의 ROWNUM / EXISTS 조합
WHEREEXISTS (
SELECT1FROM AWHERE ROWNUM=1
)
🚫 의미 자체가 Oracle 특화
👉 로직 재설계 대상
❌ 8. 힌트 / 옵티마이저 의존 SQL
/*+ INDEX(A IDX_A1) */
🚫 PostgreSQL은 무시하거나 에러
👉 인덱스 설계 + ANALYZE로 접근해야 함
❌ 9. PL/SQL 의존 SQL
- SELECT ... INTO
- EXCEPTION WHEN
- 커서 루프 전제 SQL
🚫 MyBatis SQL로 그대로 못 옮김
👉 애플리케이션 로직으로 이동
3️⃣ 실무 권장 분류 기준 (이렇게 나누면 안전)
🔹 자동 치환 대상
- 함수 1:1 대응
- 결과 의미가 명확
- 정렬/페이징/조인 구조 안 건드림
🔹 수동 전환 대상
- 페이징
- JOIN
- 날짜 계산
- 비즈니스 분기 로직
- 성능 의존 SQL
4️⃣ 한 줄 요약 (이 문서의 핵심)
- 자동 치환은 “문법”이 아니라 “의미가 같을 때만” 허용
- MyBatis SQL에서
- NVL, SYSDATE, DUAL → 자동화 가능
- ROWNUM, MERGE, (+), DECODE → 자동화 금지
- 틀린 결과는 에러보다 더 위험하다
'실험실 > db이행' 카테고리의 다른 글
| Ora2Pg가 지원하는 SQL 변환 범위 (0) | 2026.01.30 |
|---|---|
| 제로베이스 설치 시 보안 · 운영 · 이중화 전략 (0) | 2026.01.24 |
| Ora2Pg로 변환 후 “오브젝트별로” 직접 체크/수정해야 하는 포인트 정리 (0) | 2026.01.24 |
| 2컨테이너 실용화 (1) | 2026.01.22 |
| 결과파일의 관리 (0) | 2026.01.22 |
댓글