DB·SQL 실무 가이드 · 부록

다른 DBMS를 만났을 때

Oracle 기준으로 익힌 내용을 다른 제품에서 쓸 때 실제로 갈리는 지점만 모았습니다. 개념은 대부분 그대로 통하고, 달라지는 것은 문법의 표면입니다.

작성 기준2026년 7월버전과 지원 현황은 이후 달라질 수 있으니 공식 문서를 함께 확인하세요.

인덱스가 언제 안 타는지, 실행계획을 어떻게 읽는지, 트랜잭션이 어떻게 꼬이는지는 제품과 무관하게 같은 원리로 동작합니다. 이 문서는 그 위에서 실제로 달라지는 문법만 다룹니다.

버전에 따라 지원 여부가 달라지는 항목이 많습니다. 표에 표기한 최소 버전은 참고용이고, 적용 전에는 운영 중인 버전의 공식 문서를 확인합니다.

01

행 제한과 페이징

이관할 때 가장 먼저 손대야 하는 부분입니다. 문법이 제품마다 완전히 다릅니다.

항목OracleMSSQLMySQLPostgreSQL
상위 N건FETCH FIRST n ROWS ONLY (12c+) / ROWNUM <= nSELECT TOP (n) ... / OFFSET FETCHLIMIT nLIMIT n / FETCH FIRST n ROWS ONLY
페이징OFFSET m ROWS FETCH NEXT n ROWS ONLY (12c+)ORDER BY ... OFFSET m ROWS FETCH NEXT n ROWS ONLY (2012+)LIMIT n OFFSET mLIMIT n OFFSET m
행 번호ROWNUM (의사 컬럼) / ROW_NUMBER() OVERROW_NUMBER() OVERROW_NUMBER() OVER (8.0+)ROW_NUMBER() OVER
  • 페이징 · Oracle 11g 이하는 ROWNUM 중첩 인라인뷰를 써야 합니다. MSSQL의 OFFSET FETCH 는 ORDER BY 가 필수입니다.
  • 행 번호 · ROWNUM 은 Oracle과 Tibero 고유입니다. 이관 시 ROW_NUMBER() 로 바꿔야 합니다.
02

NULL과 문자열

오류 없이 결과만 달라지는 영역이라 이관 후 검증에서 놓치기 쉽습니다.

항목OracleMSSQLMySQLPostgreSQL
빈 문자열'' 는 NULL과 동일'' 와 NULL을 구분'' 와 NULL을 구분'' 와 NULL을 구분
문자열 결합|| 또는 CONCAT (NULL은 무시)+ 또는 CONCAT (NULL이면 결과 NULL)CONCAT (|| 는 기본적으로 OR)||
NULL 대체NVL, NVL2, COALESCEISNULL, COALESCEIFNULL, COALESCECOALESCE
NULL 정렬NULL이 가장 큼 (ASC에서 뒤)NULL이 가장 작음 (ASC에서 앞)NULL이 가장 작음 (ASC에서 앞)NULL이 가장 큼 (ASC에서 뒤)
부분 문자열SUBSTR, INSTRSUBSTRING, CHARINDEXSUBSTRING, LOCATESUBSTRING, POSITION
  • 빈 문자열 · Oracle만 다릅니다. 이관 시 데이터와 조건문 양쪽을 모두 점검해야 하는 대표적인 항목입니다.
  • 문자열 결합 · Oracle은 'A' || NULL 이 'A'지만, MSSQL의 'A' + NULL 은 NULL입니다. 문자열 조립 로직이 조용히 깨집니다.
  • NULL 대체 · COALESCE 는 네 제품 모두 지원합니다. 이관 가능성이 있으면 처음부터 COALESCE 를 쓰는 편이 낫습니다.
  • NULL 정렬 · NULLS FIRST / NULLS LAST 는 Oracle과 PostgreSQL만 지원합니다. MSSQL과 MySQL은 CASE로 정렬 키를 만들어야 합니다.
03

날짜와 시간

타입의 정밀도가 달라 이관 시 값이 잘리거나 늘어납니다.

항목OracleMSSQLMySQLPostgreSQL
현재 시각SYSDATE, SYSTIMESTAMPGETDATE(), SYSDATETIME()NOW(), CURDATE()NOW(), CURRENT_DATE
DATE 타입연월일시분초 포함 (초 단위)DATE는 날짜만, DATETIME2 가 시각 포함DATE는 날짜만, DATETIME 이 시각 포함DATE는 날짜만, TIMESTAMP 가 시각 포함
문자열 변환TO_CHAR(dt, 'YYYY-MM-DD'), TO_DATEFORMAT, CONVERTDATE_FORMAT, STR_TO_DATETO_CHAR, TO_DATE
날짜 연산dt + 1 (일 단위), ADD_MONTHSDATEADD(day, 1, dt)DATE_ADD(dt, INTERVAL 1 DAY)dt + INTERVAL '1 day'
  • DATE 타입 · Oracle의 DATE를 다른 제품의 DATE로 그대로 옮기면 시분초가 잘립니다. DATETIME 계열로 매핑해야 합니다.
  • 날짜 연산 · Oracle에서 날짜에 숫자를 더하면 일 단위로 더해집니다. 이 관용구는 다른 제품에서 통하지 않습니다.
04

키 생성과 UPSERT

테이블 정의와 배치 로직을 함께 바꿔야 하는 영역입니다.

항목OracleMSSQLMySQLPostgreSQL
자동 증가SEQUENCE / IDENTITY (12c+)IDENTITY / SEQUENCE (2012+)AUTO_INCREMENTGENERATED AS IDENTITY / SERIAL
UPSERTMERGEMERGEINSERT ... ON DUPLICATE KEY UPDATEINSERT ... ON CONFLICT DO UPDATE
더미 테이블FROM DUAL 필수FROM 생략 가능FROM 생략 가능 (DUAL도 허용)FROM 생략 가능
  • UPSERT · MERGE 를 쓴 배치는 MySQL, PostgreSQL로 옮길 때 전면 재작성이 필요합니다.
05

집합 연산과 계층 쿼리

Oracle 고유 문법이 많아 단순 치환이 안 되는 부분입니다.

항목OracleMSSQLMySQLPostgreSQL
차집합MINUSEXCEPTEXCEPT (8.0.31+)EXCEPT
계층 쿼리CONNECT BY / START WITHWITH RECURSIVE (재귀 CTE)WITH RECURSIVE (8.0+)WITH RECURSIVE
조건 분기DECODE, CASEIIF, CASEIF, CASECASE
  • 차집합 · MINUS 는 Oracle과 Tibero 고유입니다. 구버전 MySQL에는 대체 문법이 없어 NOT EXISTS 로 다시 써야 합니다.
  • 계층 쿼리 · CONNECT BY 는 재귀 CTE로 다시 설계해야 합니다. LEVEL, SYS_CONNECT_BY_PATH 같은 부가 기능도 직접 구현해야 합니다.
  • 조건 분기 · CASE 는 모든 제품이 지원합니다. DECODE 는 Oracle과 Tibero 전용입니다.
06

실행계획 확인

성능 진단 방법은 제품마다 완전히 다릅니다. 개념은 같아도 도구는 새로 익혀야 합니다.

항목OracleMSSQLMySQLPostgreSQL
예측 계획EXPLAIN PLAN FOR + DBMS_XPLAN.DISPLAYSET SHOWPLAN_ALL ON / 예상 실행 계획EXPLAINEXPLAIN
실제 계획DBMS_XPLAN.DISPLAY_CURSOR('ALLSTATS LAST')SET STATISTICS PROFILE ON / 실제 실행 계획EXPLAIN ANALYZE (8.0.18+)EXPLAIN (ANALYZE, BUFFERS)
블록 읽기 측정SET AUTOTRACE ON STATISTICSSET STATISTICS IO ONperformance_schemaEXPLAIN (ANALYZE, BUFFERS)
힌트/*+ INDEX(...) */ 주석 형태WITH (INDEX(...)), OPTION (...)USE INDEX / FORCE INDEX기본 미지원 (확장 필요)
  • 실제 계획 · 예상과 실제를 비교하는 방식은 네 제품 모두 같습니다. 튜닝의 사고방식은 그대로 옮겨 갑니다.
  • 힌트 · PostgreSQL은 의도적으로 힌트를 지원하지 않습니다. 통계와 쿼리 구조로 푸는 문화라 Oracle에서 넘어가면 접근 방식을 바꿔야 합니다.
TB

Tibero는 별도 문법이 아니라 호환성 확인 대상입니다

공공기관 사업에서는 국산 DBMS 도입 요건 때문에 Tibero를 만나는 일이 잦습니다. Oracle 호환을 전면에 내세우고 있어 대부분의 문법이 그대로 통하므로, 별도 트랙 대신 차이점만 확인하는 방식이 효율적입니다.

다만 문법 호환과 성능 호환은 다릅니다. 같은 쿼리가 같은 실행계획을 탄다는 보장이 없어서, 이관 직후에는 잘 돌다가 데이터가 쌓인 뒤 특정 쿼리만 느려지는 형태로 문제가 드러나는 경우가 있습니다.

대체로 그대로 통하는 것
  • DUAL, ROWNUM, SEQUENCE, (+) 아우터 조인 구문
  • CONNECT BY / START WITH 계층 쿼리
  • DECODE, NVL, TO_CHAR 등 Oracle 내장 함수 대부분
  • MINUS, INTERSECT 집합 연산
  • /*+ ... */ 힌트 문법
  • PL/SQL에 대응하는 PSM 프로시저 언어
확인
따로 확인해야 하는 것
  • CLI 도구가 sqlplus 가 아닌 tbsql 입니다. 사용법은 거의 같습니다.
  • 일부 내장 패키지와 최신 Oracle 전용 기능은 지원되지 않거나 동작이 다릅니다.
  • 옵티마이저가 같은 쿼리에 다른 실행계획을 세울 수 있습니다. 문법 호환과 성능 호환은 별개입니다.
  • 진단과 모니터링 도구 체계가 다릅니다. Oracle의 AWR에 대응하는 별도 기능을 확인해야 합니다.
  • 지원 범위는 Tibero 버전과 호환 모드 설정에 따라 달라집니다. 실제 대상 버전 문서를 확인해야 합니다.
이관

이관할 때 먼저 확인할 것

빈 문자열과 NULL

Oracle에서 나갈 때와 들어올 때 모두 문제가 됩니다. 이관 후 NULL 건수를 원본과 대조하는 검증을 반드시 넣습니다.

날짜 정밀도

Oracle DATE는 시분초를 포함합니다. 다른 제품의 DATE로 매핑하면 시각이 잘립니다. DATETIME 계열로 받아야 합니다.

정렬 순서 변화

NULL 정렬 방향과 문자 정렬 규칙이 달라 화면의 목록 순서가 바뀝니다. 오류가 안 나서 사용자 문의로 발견됩니다.

실행계획은 다시 검증

문법이 통해도 옵티마이저 판단은 다릅니다. 주요 쿼리는 이관 후 실행계획과 응답시간을 다시 측정합니다.

MERGE와 계층 쿼리

MERGE, CONNECT BY, ROWNUM 페이징은 단순 치환이 안 됩니다. 이관 범위를 잡을 때 이 세 가지를 먼저 검색해 물량을 파악합니다.

양방향 대사

MINUS나 EXCEPT로 원본에서 대상을, 대상에서 원본을 각각 빼서 양쪽 모두 0건인지 확인합니다. 한 방향만 보면 놓칩니다.

범위 산정 요령

이관 물량을 가늠할 때는 소스에서 MERGE, CONNECT BY, ROWNUM, DECODE, (+) 다섯 가지를 먼저 검색해 봅니다. 단순 치환이 안 되는 것들이라 이 개수가 곧 재작성 공수입니다.