•
암시적 형변환의 위험을 알고 명시적 형변환을 쓸 수 있다.
•
TO_CHAR · TO_DATE · TO_NUMBER 를 포맷 모델과 함께 사용할 수 있다.
•
NVL · NVL2 · NULLIF · COALESCE 네 함수의 동작을 정확히 구분할 수 있다.
•
단순 CASE와 검색 CASE 를 구분하고, ELSE 생략 시의 결과를 예측할 수 있다.
•
DECODE가 등가비교만 가능하다는 한계를 알고 CASE와 골라 쓸 수 있다.
1. 형변환 개요
1) 데이터 타입을 바꾸는 세 가지 방향
함수 | 방향 | 예 |
TO_CHAR | 숫자 → 문자
날짜 → 문자 | TO_CHAR(SAL, '999,999') |
TO_DATE | 문자 → 날짜 | TO_DATE('1981-01-01', 'YYYY-MM-DD') |
TO_NUMBER | 문자 → 숫자 | TO_NUMBER('1234') |
숫자
날짜는 직접 변환할 수 없습니다. 반드시 문자를 거쳐야 합니다.2) 암시적 형변환 vs 명시적 형변환 

구분 | 의미 | 누가 하는가 |
암시적 형변환 (Implicit) | DB가 알아서 타입을 맞춤 | 오라클이 자동으로 |
명시적 형변환 (Explicit) | 개발자가 함수로 직접 지정 | TO_CHAR 등으로 직접 |
-- ============================================================
-- 【이해용 예제】 오라클은 알아서 타입을 맞춰준다 (암시적 형변환)
-- ============================================================
SELECT '100' + 1 AS 문자더하기숫자, -- 문자 '100' 을 숫자 100 으로 자동 변환
100 || '원' AS 숫자붙이기문자 -- 숫자 100 을 문자 '100' 으로 자동 변환
FROM DUAL;
-- 문자더하기숫자 숫자붙이기문자
-- -------------- --------------
-- 101 100원
-- → 편리해 보이지만 위험하다 ⚠️
SQL
복사
-- ============================================================
-- 【시험용 예제】 암시적 형변환이 위험한 두 가지 이유 ★★
-- ============================================================
-- ⚠️ 위험 ① 데이터에 따라 '오류'가 발생한다
SELECT '100A' + 1 FROM DUAL;
-- ORA-01722: invalid number
-- → 숫자로 바꿀 수 없는 문자가 섞이면 즉시 오류. 개발 중엔 몰랐다가 운영에서 터진다.
-- ⚠️ 위험 ② 인덱스를 사용하지 못해 느려진다
-- EMPNO 는 숫자 컬럼인데 문자와 비교하면
SELECT * FROM EMP WHERE EMPNO = '7369';
-- → 오라클이 내부적으로 EMPNO 를 문자로 바꿔 비교할 수 있고,
-- 그러면 EMPNO 에 걸린 인덱스를 타지 못해 전체 테이블을 훑는다 (옵티마이저)
-- ✅ 원칙 : 타입은 '명시적으로' 맞춘다
SELECT * FROM EMP WHERE EMPNO = 7369; -- 숫자는 숫자끼리
SELECT * FROM EMP WHERE EMPNO = TO_NUMBER('7369'); -- 또는 명시적 변환
-- ⭐ 시험 포인트
-- "암시적 형변환은 편리하지만, 오류 가능성과 성능 저하 때문에 권장하지 않는다"
SQL
복사
2. TO_CHAR — 문자로 바꾸기 

1) 날짜 → 문자 : 날짜 포맷 모델
포맷 | 의미 | 1980-12-17 이면 |
YYYY | 연도 4자리 | 1980 |
YY | 연도 2자리 | 80 |
MM | 월 (2자리) | 12 |
MON | 월 약어 | 12월 |
MONTH | 월 전체 | 12월 |
DD | 일 (2자리) | 17 |
DAY | 요일 전체 | 수요일 |
DY | 요일 약어 | 수 |
D | 요일 숫자 (일=1) | 4 |
Q | 분기 | 4 |
HH24 | 24시간제 시 | 00 |
HH | 12시간제 시 | 12 |
MI | 분 | 00 |
SS | 초 | 00 |

최다 실수 — MM 과 MIMM = 월(Month), MI = 분(Minute) 입니다.
"분이니까 MM" 이라고 쓰면 월이 나옵니다. 매년 출제됩니다.
HH 는 12시간제입니다. 오후 3시가 03 으로 나옵니다.
24시간제로 보려면 반드시 HH24 를 써야 합니다.-- ============================================================
-- 【이해용 예제】 입사일을 원하는 형태로 표현하기
-- ============================================================
SELECT ENAME,
HIREDATE AS 원본,
TO_CHAR(HIREDATE, 'YYYY-MM-DD') AS 기본형,
TO_CHAR(HIREDATE, 'YYYY"년" MM"월" DD"일"') AS 한글형,
-- 큰따옴표 안의 글자는 '포맷이 아닌 그냥 문자' 로 취급된다
TO_CHAR(HIREDATE, 'DAY') AS 요일,
TO_CHAR(HIREDATE, 'Q') AS 분기
FROM EMP
WHERE DEPTNO = 10;
-- ENAME 원본 기본형 한글형 요일 분기
-- ------ ---------- ---------- ------------------ ------ ----
-- CLARK 1981-06-09 1981-06-09 1981년 06월 09일 화요일 2
-- KING 1981-11-17 1981-11-17 1981년 11월 17일 화요일 4
-- MILLER 1982-01-23 1982-01-23 1982년 01월 23일 토요일 1
--
-- ⚠️ DAY, MON 등의 결과는 DB 언어 설정(NLS_LANGUAGE)에 따라 한글/영문이 달라진다
SQL
복사
-- ============================================================
-- 【시험용 예제】 MM 과 MI 를 헷갈리면 어떻게 되는가 ★★
-- ============================================================
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') AS 올바른표기,
TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MM:SS') AS 잘못된표기
-- ↑ 분 자리에 MM(월)을 썼다!
FROM DUAL;
-- 올바른표기 잘못된표기
-- --------------------- ---------------------
-- 2026-07-20 14:35:07 2026-07-20 14:07:07
-- ↑ 분이 아니라 '월(07)' 이 찍혔다 ⚠️
--
-- ⭐ 암기: M M → Month(월) / M I → MInute(분)
SQL
복사
2) 숫자 → 문자 : 숫자 포맷 모델 
포맷 | 의미 | 800 에 적용하면 |
9 | 자리 표시 (빈자리는 공백) | ' 800' |
0 | 자리 표시 (빈자리는 0) | '000800' |
, | 천 단위 구분 기호 | ' 800' |
. | 소수점 | — |
L | 지역 통화 기호 | '₩ 800' |
-- ============================================================
-- 【시험용 예제】 9 와 0 의 차이 ★
-- ============================================================
SELECT ENAME,
SAL,
TO_CHAR(SAL, '999,999') AS "9사용", -- 빈 자리는 공백
TO_CHAR(SAL, '000,000') AS "0사용", -- 빈 자리는 0으로 채움
TO_CHAR(SAL, 'L999,999') AS 통화표시
FROM EMP
WHERE DEPTNO = 10;
-- ENAME SAL 9사용 0사용 통화표시
-- ------ ----- -------- -------- ----------
-- CLARK 2450 2,450 002,450 ₩ 2,450
-- KING 5000 5,000 005,000 ₩ 5,000
-- MILLER 1300 1,300 001,300 ₩ 1,300
--
-- ⭐ 시험 포인트
-- 9 = 자리가 남으면 공백 / 0 = 자리가 남으면 0으로 채움
-- TO_CHAR 의 결과는 '문자' 이므로 오른쪽 정렬이 아니라 왼쪽 정렬로 표시된다
SQL
복사
3) EXTRACT 와의 차이 — 09강 회수 
EXTRACT(YEAR FROM 날짜) | TO_CHAR(날짜, 'YYYY') | |
반환 타입 | 숫자 | 문자 |
비교 방식 | = 1981 | = '1981' |
월 표기 | 6 (앞의 0 없음) | '06' (두 자리 유지) |
표준 여부 | ANSI 표준 | Oracle 전용 |
-- 같은 결과를 내는 두 가지 방법 (1981년 입사자)
SELECT ENAME FROM EMP WHERE EXTRACT(YEAR FROM HIREDATE) = 1981; -- 숫자 비교
SELECT ENAME FROM EMP WHERE TO_CHAR(HIREDATE, 'YYYY') = '1981'; -- 문자 비교
-- → 둘 다 10건
SQL
복사
3. TO_DATE — 날짜로 바꾸기 

TO_DATE(문자열, 포맷)
문자열을 그 포맷으로 해석해서 날짜로 바꿉니다.
-- ============================================================
-- 【시험용 예제】 날짜 비교의 올바른 방법 ★★ (08강 회수)
-- ============================================================
-- ⚠️ 위험한 방법 : 문자열을 그대로 날짜와 비교
SELECT ENAME, HIREDATE FROM EMP WHERE HIREDATE >= '1981-01-01';
-- → DB의 날짜 형식 설정(NLS_DATE_FORMAT)이 'YYYY-MM-DD' 가 아니면
-- ORA-01861: literal does not match format string 오류 발생 ⚠️
-- 설정에 따라 되기도 하고 안 되기도 하는 '불안정한 SQL' 이다.
-- ✅ 안전한 방법 : TO_DATE 로 형식을 명시한다
SELECT ENAME, HIREDATE
FROM EMP
WHERE HIREDATE >= TO_DATE('1981-01-01', 'YYYY-MM-DD');
-- 문자열 ──────┘ └────── 이 문자열을 이렇게 해석하라
-- ENAME HIREDATE
-- ------ ----------
-- ALLEN 1981-02-20
-- WARD 1981-02-22
-- ... → 13건 (SMITH 제외)
-- ✅ 기간 조회도 마찬가지
SELECT ENAME, HIREDATE
FROM EMP
WHERE HIREDATE BETWEEN TO_DATE('1981-01-01', 'YYYY-MM-DD')
AND TO_DATE('1981-12-31', 'YYYY-MM-DD');
-- → 1981년에 입사한 사원 10건
--
-- ⭐ 시험·실무 원칙 : 날짜 리터럴은 반드시 TO_DATE 로 명시적 변환한다
SQL
복사
DATE 리터럴 — 더 간단한 대안
-- ANSI 표준 DATE 리터럴 (반드시 'YYYY-MM-DD' 형식이어야 함)
SELECT ENAME FROM EMP WHERE HIREDATE >= DATE '1981-01-01';
-- → TO_DATE 와 동일한 결과. 형식이 고정되어 있어 오히려 안전하다.
SQL
복사
TO_NUMBER — 숫자로 바꾸기
-- ============================================================
-- 【이해용 예제】 문자로 저장된 값을 계산에 쓰기
-- PLAYER.JOIN_YYYY 는 CHAR(4) 이므로 '문자' 다
-- ============================================================
SELECT PLAYER_NAME AS 선수명,
JOIN_YYYY AS "입단연도(문자)",
TO_NUMBER(JOIN_YYYY) AS "입단연도(숫자)",
2026 - TO_NUMBER(JOIN_YYYY) AS 활동연차 -- 숫자로 바꿔야 뺄 수 있다
FROM PLAYER
WHERE JOIN_YYYY IS NOT NULL
AND ROWNUM <= 3;
-- 선수명 입단연도(문자) 입단연도(숫자) 활동연차
-- ------- -------------- -------------- --------
-- 김철수 2012 2012 14
-- 이영희 2010 2010 16
-- 09강에서 SUBSTR 로 잘라낸 값도 '문자' 이므로 계산하려면 변환이 필요하다
SELECT PLAYER_NAME,
SUBSTR(PLAYER_ID, 1, 4) AS "연도(문자)",
TO_NUMBER(SUBSTR(PLAYER_ID, 1, 4)) AS "연도(숫자)"
FROM PLAYER
WHERE ROWNUM <= 3;
SQL
복사
-- ============================================================
-- 【시험용 예제】 콤마가 들어간 문자는 그냥 변환되지 않는다 ★
-- ============================================================
SELECT TO_NUMBER('1234') AS 정상 FROM DUAL;
-- → 1234 ✅
SELECT TO_NUMBER('1,234') FROM DUAL;
-- ORA-01722: invalid number
-- → 콤마 때문에 숫자로 해석되지 않는다 ⚠️
SELECT TO_NUMBER('1,234', '9,999') AS 포맷지정 FROM DUAL;
-- → 1234 ✅ (포맷을 알려주면 해석할 수 있다)
SQL
복사
5. NULL 관련 함수 4종 


이 4개는 반드시 구분해서 알아야 합니다.1) 한 표로 정리 


함수 | 문법 | 동작 |
NVL | NVL(A, B) | A가 NULL이면 B, 아니면 A |
NVL2 | NVL2(A, B, C) | A가 NULL이 아니면 B, NULL이면 C ![]() |
NULLIF | NULLIF(A, B) | A와 B가 같으면 NULL, 다르면 A |
COALESCE | COALESCE(A, B, C, …) | 인자 중 첫 번째 NULL이 아닌 값 |
NVL2 의 순서가 최대 함정입니다.NVL2(A, B, C) — "A가 있으면 B, 없으면 C"NVL(A, B) 과 헷갈려 "NULL이면 B"라고 외우면 정반대가 됩니다.2) NVL — 07강 파생속성 문제 최종 해결
-- ============================================================
-- 【시험용 예제】 NULL 때문에 계산이 깨지던 문제 해결 ★★
-- ============================================================
SELECT ENAME,
SAL,
COMM,
SAL + COMM AS "❌ 그냥 계산",
SAL + NVL(COMM, 0) AS "✅ NVL 적용",
NVL(COMM, 0) AS "커미션(NULL→0)"
FROM EMP
WHERE DEPTNO = 30;
-- ENAME SAL COMM ❌ 그냥 계산 ✅ NVL 적용 커미션(NULL→0)
-- ------ ----- ----- ------------ ----------- --------------
-- ALLEN 1600 300 1900 1900 300
-- WARD 1250 500 1750 1750 500
-- MARTIN 1250 1400 2650 2650 1400
-- BLAKE 2850 (NULL) (NULL) ⚠️ 2850 0
-- TURNER 1500 0 1500 1500 0
-- JAMES 950 (NULL) (NULL) ⚠️ 950 0
--
-- ⭐ 06강 → 07강 → 10강으로 이어진 숙제가 여기서 끝났습니다.
-- ⚠️ NVL 의 두 인자는 '데이터 타입이 호환' 되어야 한다
-- NVL(COMM, '없음') → ORA-01722 (숫자 컬럼에 문자를 넣을 수 없음)
SQL
복사
3) NVL2 — 있으면 A, 없으면 B
-- ============================================================
-- 【이해용 예제】 커미션 수령 여부를 표시하기
-- ============================================================
SELECT ENAME,
COMM,
NVL2(COMM, '수령', '미수령') AS 커미션여부
-- ↑값 ↑NULL아닐때 ↑NULL일때
FROM EMP
WHERE DEPTNO = 30;
-- ENAME COMM 커미션여부
-- ------ ----- ----------
-- ALLEN 300 수령
-- WARD 500 수령
-- MARTIN 1400 수령
-- BLAKE (NULL) 미수령
-- TURNER 0 수령 ← 0 은 NULL이 아니다! (06강) ⭐
-- JAMES (NULL) 미수령
--
-- ⭐ TURNER 의 커미션 0 은 '값이 있는 것' 이므로 '수령' 으로 판정된다.
-- 이 지점이 시험에 자주 나옵니다.
SQL
복사
4) NULLIF — 같으면 NULL
-- ============================================================
-- 【시험용 예제】 특정 값을 NULL로 만들고 싶을 때 ★
-- "급여가 정확히 3000인 사원은 급여를 표시하지 않는다"
-- ============================================================
SELECT ENAME,
SAL,
NULLIF(SAL, 3000) AS 결과
-- ↑A ↑B A와 B가 같으면 NULL, 다르면 A
FROM EMP
WHERE DEPTNO = 20;
-- ENAME SAL 결과
-- ------ ----- ------
-- SMITH 800 800
-- JONES 2975 2975
-- SCOTT 3000 (NULL) ← 3000 과 같으므로 NULL ⚠️
-- ADAMS 1100 1100
-- FORD 3000 (NULL) ← 3000 과 같으므로 NULL
--
-- ⭐ NULLIF(A, B) 는 CASE 로 쓰면 이렇게 된다
-- CASE WHEN A = B THEN NULL ELSE A END
SQL
복사
5) COALESCE — 첫 번째 NOT NULL
-- ============================================================
-- 【시험용 예제】 여러 후보 중 값이 있는 것을 골라내기 ★
-- "커미션이 있으면 커미션, 없으면 급여, 그것도 없으면 0"
-- ============================================================
SELECT ENAME,
COMM,
SAL,
COALESCE(COMM, SAL, 0) AS 지급기준액
-- ① ② ③ 왼쪽부터 검사해 처음 NULL이 아닌 값을 반환
FROM EMP
WHERE DEPTNO = 30;
-- ENAME COMM SAL 지급기준액
-- ------ ----- ----- ----------
-- ALLEN 300 1600 300 ← COMM 이 있으므로 COMM
-- WARD 500 1250 500
-- MARTIN 1400 1250 1400
-- BLAKE (NULL) 2850 2850 ← COMM 이 NULL 이므로 SAL
-- TURNER 0 1500 0 ← 0 도 값이므로 COMM 채택 ⭐
-- JAMES (NULL) 950 950
--
-- ⭐ COALESCE 는 인자 개수 제한이 없다 → NVL 을 여러 번 중첩한 것과 같다
-- COALESCE(A, B, C) = NVL(NVL(A, B), C)
SQL
복사
6) 네 함수 종합 비교
상황 | NVL(COMM,0) | NVL2(COMM,'Y','N') | NULLIF(COMM,0) | COALESCE(COMM,SAL) |
COMM = 300 | 300 | Y | 300 | 300 |
COMM = 0 | 0 | Y | NULL | 0 |
COMM = NULL | 0 | N | NULL | SAL 값 |
6. CASE — 조건 분기 


1) 두 가지 형태
단순 CASE | 검색 CASE | |
문법 | CASE 컬럼 WHEN 값 THEN … | CASE WHEN 조건 THEN … |
비교 방식 | 등가비교(=)만 | > < BETWEEN IS NULL 등 자유 |
용도 | 코드값 변환 | 범위 구간 나누기 |
2) 단순 CASE — 코드값을 이름으로
-- ============================================================
-- 【이해용 예제】 부서번호를 부서명으로 바꾸기
-- ============================================================
SELECT ENAME,
DEPTNO,
CASE DEPTNO -- 이 컬럼의 값을
WHEN 10 THEN '경리부' -- 10 이면 '경리부'
WHEN 20 THEN '연구부' -- 20 이면 '연구부'
WHEN 30 THEN '영업부' -- 30 이면 '영업부'
ELSE '기타' -- 어느 것도 아니면 '기타'
END AS 부서명 -- CASE 는 반드시 END 로 닫는다
FROM EMP;
-- ENAME DEPTNO 부서명
-- ------ ------ ------
-- SMITH 20 연구부
-- ALLEN 30 영업부
-- CLARK 10 경리부
SQL
복사
3) 검색 CASE — 범위로 등급 나누기 
-- ============================================================
-- 【시험용 예제】 급여 구간별 등급 부여 ★★
-- ⚠️ 이런 '범위 조건' 은 단순 CASE 로는 불가능하다
-- ============================================================
SELECT ENAME,
SAL,
CASE WHEN SAL >= 3000 THEN 'A등급' -- 위에서부터 순서대로 검사
WHEN SAL >= 2000 THEN 'B등급' -- 앞 조건이 FALSE 일 때만 검사됨
WHEN SAL >= 1000 THEN 'C등급'
ELSE 'D등급'
END AS 급여등급
FROM EMP
ORDER BY SAL DESC;
-- ENAME SAL 급여등급
-- ------ ----- --------
-- KING 5000 A등급
-- SCOTT 3000 A등급
-- FORD 3000 A등급
-- JONES 2975 B등급
-- BLAKE 2850 B등급
-- CLARK 2450 B등급
-- ALLEN 1600 C등급
-- TURNER 1500 C등급
-- MILLER 1300 C등급
-- WARD 1250 C등급
-- MARTIN 1250 C등급
-- ADAMS 1100 C등급
-- JAMES 950 D등급
-- SMITH 800 D등급
--
-- ⭐ 중요: WHEN 은 '위에서부터 순서대로' 검사하고, 처음 TRUE 인 곳에서 멈춘다.
-- 그래서 SAL=5000 은 'SAL >= 3000' 에서 걸려 A등급이 되고
-- 아래의 'SAL >= 2000' 은 아예 검사되지 않는다.
-- ⚠️ 순서를 거꾸로 쓰면(1000 → 2000 → 3000) 모두 C등급이 되어버린다!
SQL
복사
4)
ELSE 를 생략하면 NULL 

-- ============================================================
-- 【시험용 예제】 ELSE 생략의 함정 ★★
-- ============================================================
SELECT ENAME,
DEPTNO,
CASE DEPTNO
WHEN 10 THEN '경리부'
WHEN 20 THEN '연구부'
END AS "ELSE 없음" -- ELSE 를 쓰지 않았다
FROM EMP;
-- ENAME DEPTNO ELSE 없음
-- ------ ------ ---------
-- CLARK 10 경리부
-- SMITH 20 연구부
-- ALLEN 30 (NULL) ← 어느 WHEN 에도 안 걸림 → NULL ⚠️
-- BLAKE 30 (NULL)
--
-- ⭐ 시험 포인트
-- CASE 에 ELSE 가 없고 어떤 WHEN 도 만족하지 않으면 결과는 'NULL' 이다.
-- (오류가 나거나 공백이 되는 것이 아니다)
SQL
복사
5) CASE 로 NULL 함수 흉내내기
NULL 함수 | 같은 뜻의 CASE |
NVL(A, B) | CASE WHEN A IS NULL THEN B ELSE A END |
NVL2(A, B, C) | CASE WHEN A IS NOT NULL THEN B ELSE C END |
NULLIF(A, B) | CASE WHEN A = B THEN NULL ELSE A END |
COALESCE(A, B) | CASE WHEN A IS NOT NULL THEN A ELSE B END |
CASE 가 가장 강력하고 범용적입니다. NULL 함수들은 자주 쓰는 패턴을 짧게 쓴 것뿐입니다.7. DECODE — 조건 함수 

1) 문법과 동작
DECODE(표현식, 값1, 결과1, 값2, 결과2, …, 기본값)
표현식이 값1과 같으면 결과1, 값2와 같으면 결과2 … 어느 것도 아니면 기본값
-- ============================================================
-- 【이해용 예제】 DECODE 로 부서명 표시하기 (단순 CASE 와 동일)
-- ============================================================
SELECT ENAME,
DEPTNO,
DECODE(DEPTNO, 10, '경리부', -- DEPTNO 가 10 이면 '경리부'
20, '연구부', -- 20 이면 '연구부'
30, '영업부', -- 30 이면 '영업부'
'기타') -- 마지막 짝 없는 인자 = 기본값(ELSE)
AS 부서명
FROM EMP;
-- ENAME DEPTNO 부서명
-- ------ ------ ------
-- SMITH 20 연구부
-- ALLEN 30 영업부
-- CLARK 10 경리부
-- 위와 완전히 같은 결과를 내는 CASE
SELECT ENAME, DEPTNO,
CASE DEPTNO WHEN 10 THEN '경리부'
WHEN 20 THEN '연구부'
WHEN 30 THEN '영업부'
ELSE '기타' END AS 부서명
FROM EMP;
SQL
복사
2)
DECODE 의 결정적 한계 — 등가비교만 가능 


-- ============================================================
-- 【시험용 예제】 범위 조건은 DECODE 로 못 한다 ★★★
-- ============================================================
-- ❌ DECODE 로는 이런 걸 쓸 수 없다
-- DECODE(SAL >= 3000, TRUE, 'A등급', ...) ← 문법적으로 불가능
-- ✅ 범위 조건은 반드시 CASE
SELECT ENAME, SAL,
CASE WHEN SAL >= 3000 THEN 'A등급'
WHEN SAL >= 2000 THEN 'B등급'
ELSE 'C등급' END AS 등급
FROM EMP;
-- 💡 굳이 DECODE 로 하려면 SIGN 함수 같은 편법을 써야 한다 (권장하지 않음)
SELECT ENAME, SAL,
DECODE(SIGN(SAL - 3000), 1, 'A등급', 0, 'A등급', '그 외') AS 등급
-- SIGN : 양수면 1, 0이면 0, 음수면 -1 (09강)
FROM EMP;
-- → 억지로 되긴 하지만 읽기 어렵다. CASE 를 쓰는 게 정답이다.
SQL
복사
3) DECODE 만의 장점 — NULL 을 비교할 수 있다 
-- ============================================================
-- 【시험용 예제】 DECODE 는 NULL 끼리도 '같다' 고 판단한다 ★
-- ============================================================
SELECT ENAME,
COMM,
DECODE(COMM, NULL, '커미션 없음', '커미션 있음') AS 판정
-- ↑ NULL 과의 등가비교가 '동작한다'
FROM EMP
WHERE DEPTNO = 30;
-- ENAME COMM 판정
-- ------ ----- ------------
-- ALLEN 300 커미션 있음
-- BLAKE (NULL) 커미션 없음 ← DECODE 는 NULL 을 잡아낸다 ✅
-- TURNER 0 커미션 있음
--
-- ⚠️ 08강에서 배운 WHERE 절의 규칙과 다르다는 점에 주의!
-- WHERE COMM = NULL → 0건 (UNKNOWN)
-- DECODE(COMM, NULL, …) → 정상 동작 ✅
-- DECODE 는 내부적으로 두 NULL 을 '같은 것' 으로 취급하기 때문이다.
SQL
복사
4) DECODE vs CASE 최종 비교 
DECODE | CASE | |
표준 여부 | Oracle 전용 | ANSI 표준 (모든 DBMS) |
비교 방식 | 등가비교(=)만 | 모든 조건 가능 |
범위 조건 | 불가 | 가능 |
NULL 비교 | 가능 | IS NULL 로 가능 |
가독성 | 짧지만 인자가 많으면 난해 | 길지만 명확 |
권장 | 단순 코드 변환 | 그 외 전부 |
8. 출제 포인트 한눈에 정리
# | 꼭 외울 것 | 핵심 |
1 | 형변환 3함수 | TO_CHAR / TO_DATE / TO_NUMBER |
2 | 숫자 날짜 | 직접 변환 불가, 문자를 거쳐야 함 |
3 | 암시적 형변환 | 편리하지만 오류·성능 저하 위험 → 명시적 권장 |
4 | MM vs MI | MM=월, MI=분 ![]() |
5 | HH vs HH24 | HH는 12시간제 |
6 | 숫자 포맷 9 vs 0 | 9=공백, 0=0으로 채움 |
7 | 날짜 리터럴 | TO_DATE 또는 DATE '1981-01-01' |
8 | EXTRACT vs TO_CHAR | 숫자 vs 문자 |
9 | NVL(A,B) | A가 NULL이면 B |
10 | NVL2(A,B,C) | A가 NULL이 아니면 B, NULL이면 C ![]() |
11 | NULLIF(A,B) | 같으면 NULL |
12 | COALESCE | 첫 번째 NOT NULL |
13 | NVL 타입 | 두 인자의 타입이 호환되어야 함 |
14 | 값이 0 이면 | NULL이 아니다 → NULL 함수들이 그대로 통과시킴 ![]() |
15 | 단순 CASE vs 검색 CASE | 단순 = 등가비교만 / 검색 = 모든 조건 |
16 | CASE WHEN 순서 | 위에서부터 검사, 처음 TRUE에서 멈춤 |
17 | CASE ELSE 생략 | 해당 없으면 NULL ![]() |
18 | DECODE 한계 | 등가비교만, 범위 조건 불가 ![]() |
19 | DECODE 와 NULL | NULL끼리 같다고 판단 (WHERE절과 다름) |
20 | DECODE vs CASE | DECODE = Oracle 전용 / CASE = ANSI 표준 |
9. 확인 문제
Q1. TO_CHAR(800, '000,000') 과 TO_CHAR(800, '999,999') 의 결과 차이는?
정답 보기
Q2. NVL2(COMM, '수령', '미수령') 에서 COMM 이 NULL일 때 반환되는 값은?
① 수령 ② 미수령 ③ NULL ④ 오류
정답 보기
Q3. NULLIF(SAL, 3000) 에서 SAL 이 3000 일 때 결과는?
정답 보기
Q4. COALESCE(COMM, SAL, 0) 에서 COMM 이 NULL이고 SAL 이 2850일 때 결과는?
정답 보기
Q5. 아래 SQL에서 DEPTNO 가 30인 사원의 결과는?
SELECT CASE DEPTNO WHEN 10 THEN '경리부'
WHEN 20 THEN '연구부' END AS 부서명
FROM EMP;
SQL
복사
정답 보기
Q6. "급여가 3000 이상이면 A등급"을 DECODE 로 구현할 수 없는 이유는?
정답 보기








불가
가능