Oracle·Tibero, MySQL, MSSQL 의 함수 이름과 동작이 다른 부분을 한 페이지에 모았습니다.
Ctrl+F로 함수 이름(예:NVL,LISTAGG,EOMONTH,TRY_CAST)을 검색하면 됩니다. 원리는 중급·고급 레슨에서 다루므로 여기서는 바로 찾아 쓰는 표와 코드만 담습니다. Tibero 는 Oracle 호환이라 같은 칸에 묶고 다른 점만 적습니다.
자주 헷갈리는 10가지입니다. 자세한 내용은 뒤 절에 있습니다.
| 기능 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| NULL 대체 | NVL(a, b) |
IFNULL(a, b) |
ISNULL(a, b) |
'' 와 NULL |
같음('' 는 NULL) |
다름 | 다름 |
'a' 와 NULL 연결 |
'a' 가 남음 |
CONCAT 은 NULL |
+ 는 NULL |
| 문자 수 | LENGTH |
CHAR_LENGTH |
LEN (뒤 공백 무시) |
| 바이트 수 | LENGTHB |
LENGTH (한글 3) |
DATALENGTH |
| 왼쪽 채우기 | LPAD |
LPAD |
없음(RIGHT(REPLICATE)) |
| 문자열 집계 | LISTAGG |
GROUP_CONCAT |
STRING_AGG (2017) |
| 현재 시각 | SYSDATE |
NOW() |
GETDATE() |
| 말일 | LAST_DAY |
LAST_DAY |
EOMONTH (2012 부터) |
| 정규식 | 10g 부터 | 8.0 부터 | 2022 이하 없음 |
NULL 대체 함수는 이름이 DB마다 다르고, 공통은 COALESCE·NULLIF 뿐입니다.
| 기능 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| NULL 이면 대체 | NVL(a, b) |
IFNULL(a, b) |
ISNULL(a, b) |
| NULL 여부로 분기 | NVL2(a, x, y) |
IF(a IS NULL, y, x) |
IIF(a IS NULL, y, x) |
| 첫 non-NULL | COALESCE(a, b, c) |
COALESCE(a, b, c) |
COALESCE(a, b, c) |
| 같으면 NULL | NULLIF(a, b) |
NULLIF(a, b) |
NULLIF(a, b) |
| NULL 판별 | a IS NULL |
a IS NULL, ISNULL(a) |
a IS NULL |
| 대체 결과 타입 | NVL 은 첫 인자 기준 |
인자 타입 규칙 | ISNULL 은 첫 인자 타입 |
MySQL 의 ISNULL(x) 는 인자 1개짜리 판별 함수입니다. MSSQL 의 ISNULL(a, b) 와 이름만 같습니다.
MSSQL ISNULL 은 결과가 첫 인자 타입이라 뒤 값이 잘릴 수 있고, COALESCE 는 우선순위가 높은 타입을 따릅니다.
-- MSSQL
SELECT
ISNULL(CAST(NULL AS VARCHAR(2)), 'ABCDE') AS r1
, COALESCE(CAST(NULL AS VARCHAR(2)), 'ABCDE') AS r2;
-- r1 = 'AB' (잘림), r2 = 'ABCDE'| 항목 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
'' 저장 |
NULL 로 저장 | 빈 문자열 | 빈 문자열 |
WHERE col = '' |
항상 0건 | 빈 값 행 조회 | 빈 값 행 조회 |
NOT NULL 에 '' |
오류 | 허용 | 허용 |
Oracle·Tibero 는 VARCHAR2 의 '' 를 NULL 로 저장합니다. 빈 값을 찾으려면 IS NULL 로 씁니다.
| 항목 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| 오름차순 NULL 위치 | 마지막 | 처음 | 처음 |
NULLS FIRST/LAST |
지원 | 없음 | 없음 |
-- Oracle · Tibero
SELECT name, sal FROM emp ORDER BY sal DESC NULLS LAST;
-- MySQL · MSSQL (NULL 을 뒤로 보내는 우회)
SELECT
name
, sal
FROM emp
ORDER BY CASE WHEN sal IS NULL THEN 1 ELSE 0 END, sal DESC;| 항목 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| 연결 연산자 | a || b |
없음(CONCAT) |
a + b |
'a' 와 NULL 연결 |
'a' |
NULL | NULL |
| NULL 을 빈 값 취급 | 기본 동작 | CONCAT_WS |
CONCAT() 함수 |
MSSQL 은 CONCAT() 이 NULL 을 빈 문자열로 봅니다. 연산자 + 만 NULL 을 퍼뜨립니다.
MySQL CONCAT 은 인자 하나라도 NULL 이면 결과가 NULL 입니다.
관련 레슨: 중급 06 NULL 처리 함수.
| 기능 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| 문자 수 | LENGTH(s) |
CHAR_LENGTH(s) |
LEN(s) (뒤 공백 무시) |
| 바이트 수 | LENGTHB(s) |
LENGTH(s) (한글 3) |
DATALENGTH(s) |
MySQL 에서 LENGTH 는 바이트입니다. 한글 한 글자가 3이 나오는 이유입니다.
Oracle VARCHAR2(n) 도 기본은 BYTE 단위라 한글은 3바이트로 셉니다. VARCHAR2(n CHAR) 로 문자 단위를 씁니다.
| 기능 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| 부분 문자열 | SUBSTR(s, 2, 3) |
SUBSTR(s, 2, 3) |
SUBSTRING(s, 2, 3) |
| 왼쪽 n 글자 | SUBSTR(s, 1, n) |
LEFT(s, n) |
LEFT(s, n) |
| 오른쪽 n 글자 | SUBSTR(s, -n) |
RIGHT(s, n) |
RIGHT(s, n) |
| 위치 찾기 | INSTR(s, t) |
INSTR(s, t), LOCATE(t, s) |
CHARINDEX(t, s) |
| 못 찾으면 | 0 | 0 | 0 |
인자 순서가 다른 점만 주의합니다. MySQL LOCATE 와 MSSQL CHARINDEX 는 찾을 문자열이 앞입니다.
MSSQL SUBSTRING 은 길이 인자를 생략할 수 없습니다.
| 기능 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| 왼쪽 채우기 | LPAD(s, 5, '0') |
LPAD(s, 5, '0') |
아래 코드 1 |
| 오른쪽 채우기 | RPAD(s, 5, ' ') |
RPAD(s, 5, ' ') |
아래 코드 1 |
| 양쪽 공백 제거 | TRIM(s) |
TRIM(s) |
TRIM(s) (2017 부터) |
| 왼쪽·오른쪽만 | LTRIM, RTRIM |
LTRIM, RTRIM |
LTRIM, RTRIM |
MSSQL 2017 이전에는 TRIM 이 없어 LTRIM(RTRIM(s)) 로 씁니다.
LPAD 는 자릿수를 넘으면 잘립니다(Oracle·MySQL).
-- 코드 1. MSSQL 0 채우기 (5자리)
SELECT RIGHT(REPLICATE('0', 5) + CAST(id AS VARCHAR(5)), 5) AS code FROM emp;| 기능 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| 대문자·소문자 | UPPER, LOWER |
UPPER, LOWER |
UPPER, LOWER |
| 첫 글자 대문자 | INITCAP(s) |
없음 | 없음 |
| 치환 | REPLACE(s, a, b) |
REPLACE(s, a, b) |
REPLACE(s, a, b) |
| 연결 | a || b, CONCAT |
CONCAT(a, b) |
a + b, CONCAT |
Oracle CONCAT 은 인자 2개만 받습니다. 셋 이상은 || 로 이어 씁니다.
| 항목 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| 함수 | LISTAGG (11gR2) |
GROUP_CONCAT |
STRING_AGG (2017) |
| 정렬 지정 | WITHIN GROUP (ORDER BY) |
함수 안 ORDER BY |
WITHIN GROUP (ORDER BY) |
| 구분자 | 두 번째 인자 | SEPARATOR |
두 번째 인자 |
| 주의 | 정렬 절 필수 | 기본 1024 에서 잘림 | 2017 미만 없음 |
-- Oracle · Tibero
SELECT
dept
, LISTAGG(name, ', ') WITHIN GROUP (ORDER BY name) AS names
FROM emp
GROUP BY dept;
-- MySQL
SELECT
dept
, GROUP_CONCAT(name ORDER BY name SEPARATOR ', ') AS names
FROM emp
GROUP BY dept;
-- MSSQL
SELECT
dept
, STRING_AGG(name, ', ') WITHIN GROUP (ORDER BY name) AS names
FROM emp
GROUP BY dept;MySQL GROUP_CONCAT 은 group_concat_max_len 기본값 1024 에서 결과가 조용히 잘립니다.
긴 결과가 필요하면 세션에서 SET SESSION group_concat_max_len = 100000; 처럼 늘립니다.
관련 레슨: 중급 07 문자·날짜 함수, 중급 10 집계와 GROUP BY·HAVING.
| 기능 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| 현재 날짜·시각 | SYSDATE |
NOW() |
GETDATE() |
| 일 더하기 | d + 7 |
DATE_ADD(d, INTERVAL 7 DAY) |
DATEADD(DAY, 7, d) |
| 개월 더하기 | ADD_MONTHS(d, 1) |
DATE_ADD(d, INTERVAL 1 MONTH) |
DATEADD(MONTH, 1, d) |
| 시간 더하기 | d + 1/24 |
DATE_ADD(d, INTERVAL 1 HOUR) |
DATEADD(HOUR, 1, d) |
Oracle DATE 는 시·분·초를 가집니다. BETWEEN 경계가 어긋나기 쉬우므로 범위는 >= 시작 AND < 다음날 로 씁니다.
개월 더하기의 말일 처리는 아래와 같습니다.
| 시작 | 설명 | Oracle | MySQL·MSSQL |
|---|---|---|---|
| 1/31 | 옮겨 갈 날 없음 | 2/29 | 2/29 |
| 2/29(말일) | 말일에서 출발 | 3/31 | 3/29 |
옮겨 갈 날이 없으면 말일로 맞추는 것은 세 DB가 같습니다. 말일에서 출발할 때만 Oracle ADD_MONTHS 가 말일을 유지합니다.
H2 는 Oracle 모드에서도 3/29 라서 실습으로 확인되지 않습니다.
| 기능 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| 일수 차이 | b - a |
DATEDIFF(b, a) |
DATEDIFF(DAY, a, b) |
| 개월 차이 | MONTHS_BETWEEN(b, a) |
TIMESTAMPDIFF(MONTH, a, b) |
DATEDIFF(MONTH, a, b) |
| 인자 순서 | 뺄셈 | 앞 - 뒤 | 단위, 시작, 끝 |
DATEDIFF(a, b) 는 a - b 일수입니다. MSSQL 과 인자 순서가 반대입니다.DATEDIFF(단위, a, b) 는 경계를 넘은 횟수를 셉니다. 12/31 과 1/1 은 YEAR 단위로 1입니다.| 기능 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| 말일 | LAST_DAY(d) |
LAST_DAY(d) |
EOMONTH(d) (2012 부터) |
| 월 첫날(DATE) | TRUNC(d, 'MM') |
아래 코드 2 | DATEFROMPARTS (2012 부터) |
| 월 문자 | TO_CHAR(d, 'YYYY-MM') |
DATE_FORMAT(d, '%Y-%m') |
CONVERT(CHAR(7), d, 120) |
| 주 시작(월요일) | TRUNC(d, 'IW') |
아래 코드 2 | 아래 코드 2 |
월 첫날을 DATE 로 얻는 방법은 DB마다 모양이 다릅니다.
-- 코드 2. 월 첫날
-- Oracle · Tibero
SELECT TRUNC(hired, 'MM') AS first_day FROM emp;
-- MySQL (DATE 로 얻기)
SELECT DATE_SUB(hired, INTERVAL DAYOFMONTH(hired) - 1 DAY) AS first_day FROM emp;
-- MSSQL (2012 부터)
SELECT DATEFROMPARTS(YEAR(hired), MONTH(hired), 1) AS first_day FROM emp;MySQL DATE_FORMAT 은 문자열을 돌려줍니다. DATE 가 필요하면 위처럼 DATE_SUB 를 씁니다.
MSSQL FORMAT 도 2012 부터 있지만 느립니다. 대량 데이터에서는 CONVERT 나 DATEFROMPARTS 를 씁니다.
주 시작(월요일)은 Oracle 이 TRUNC(d, 'IW') 로 한 번에 얻습니다. MySQL·MSSQL 은 요일 번호를 빼는 식을 직접 세우는데, 요일 번호 체계가 DB마다 달라 설정 확인이 먼저입니다.
| 기능 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| 날짜 → 문자 | TO_CHAR(d, 'YYYY-MM-DD') |
DATE_FORMAT(d, '%Y-%m-%d') |
CONVERT(CHAR(10), d, 120) |
| 문자 → 날짜 | TO_DATE(s, 'YYYY-MM-DD') |
STR_TO_DATE(s, '%Y-%m-%d') |
CONVERT(DATE, s, 23) |
| 시:분:초 포맷 | HH24:MI:SS |
%H:%i:%s |
CONVERT 스타일 120 |
포맷 글자가 서로 다르다는 점이 핵심입니다.
| 뜻 | Oracle·Tibero | MySQL |
|---|---|---|
| 연도 4자리 | YYYY |
%Y |
| 월 | MM |
%m |
| 일 | DD |
%d |
| 시(24시간) | HH24 |
%H |
| 분 | MI |
%i |
| 초 | SS |
%s |
MSSQL CONVERT 의 스타일 번호는 120 이 yyyy-mm-dd hh:mi:ss, 23 이 yyyy-mm-dd 입니다.
MySQL 은 STR_TO_DATE 가 형식에 맞지 않으면 NULL 을 돌려줍니다.
| 기능 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| ISO 주 번호 | TO_CHAR(d, 'IW') |
WEEK(d, 3) |
DATEPART(ISO_WEEK, d) (2008 부터) |
| ISO 연도 | TO_CHAR(d, 'IYYY') |
YEARWEEK(d, 3) |
연도 별도 계산 |
| 요일 이름 | TO_CHAR(d, 'DY') |
DAYNAME(d) |
DATENAME(WEEKDAY, d) |
요일 번호 체계는 DB마다 다르므로 번호 대신 요일명 함수를 씁니다.
MSSQL DATEPART(WEEK) 는 DATEFIRST 설정 기준이라 ISO 주와 다를 수 있습니다. ISO 주는 ISO_WEEK 를 씁니다.
MySQL 은 WEEK(d, 3)·YEARWEEK(d, 3) 처럼 모드 3 이 ISO 규칙입니다.
관련 레슨: 중급 07 문자·날짜 함수, 실무 04 기간별 통계 보고서.
| 기능 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| 표준 변환 | CAST(x AS 타입) |
CAST(x AS 타입) |
CAST(x AS 타입) |
| 숫자 → 문자 | TO_CHAR(n) |
CAST(n AS CHAR) |
CAST(n AS VARCHAR(20)) |
| 문자 → 숫자 | TO_NUMBER(s) |
CAST(s AS SIGNED) |
CAST(s AS INT) |
| 스타일 지정 변환 | TO_CHAR(x, fmt) |
FORMAT(x, 2) |
CONVERT(타입, x, 스타일) |
| 천 단위 콤마 | TO_CHAR(n, '999,999') |
FORMAT(n, 0) |
FORMAT(n, 'N0') (2012 부터) |
MySQL CAST 의 대상 타입은 CHAR 입니다. CAST(x AS VARCHAR) 는 오류가 납니다.
-- MySQL
SELECT CAST(sal AS CHAR) AS sal_text FROM emp;
-- MSSQL (2012 부터 FORMAT)
SELECT FORMAT(sal, 'N0') AS sal_text FROM emp;
-- Oracle · Tibero
SELECT TO_CHAR(sal, '999,999') AS sal_text FROM emp;변환에 실패하면 오류 대신 NULL 을 돌려주는 방법입니다. 이관 검증에서 자주 씁니다.
| 항목 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| 안전 변환 | CAST ... DEFAULT NULL |
전용 함수 없음 | TRY_CAST, TRY_CONVERT |
| 지원 버전 | 12cR2 부터 | 해당 없음 | 2012 부터 |
| 변환 가능 검사 | VALIDATE_CONVERSION |
정규식 사용 | TRY_CAST(...) IS NOT NULL |
| 날짜 문자 검사 | VALIDATE_CONVERSION |
STR_TO_DATE 가 NULL |
TRY_CONVERT(DATE, s) |
-- Oracle (12cR2 부터)
SELECT
CAST(s AS NUMBER DEFAULT NULL ON CONVERSION ERROR) AS n
, VALIDATE_CONVERSION(s AS NUMBER) AS ok
FROM t;
-- MSSQL (2012 부터)
SELECT TRY_CAST(s AS INT) AS n FROM t;
-- MySQL (정규식으로 숫자 여부 검사)
SELECT s REGEXP '^[0-9]+