MySQL IF · IFNULL · NULLIF — 조건·NULL 처리 완전 정리
아래 세 줄은 짧지만 실무 SQL에서 가장 자주 등장하는 패턴을 모두 담고 있다. "조건에 따라 값을 바꾸기", "NULL이면 기본값으로 채우기", "같은 값이면 일부러 NULL로 만들기" — 이 세 가지는 리포트 쿼리, 통계 쿼리, 화면 표시용 쿼리 어디서든 쓰인다.
| 실행한 식 | 결과값 |
|---|---|
IF(100>200, '참이다', '거짓이다') |
거짓이다 |
IFNULL(NULL, '널이군요') |
널이군요 |
IFNULL(100, '널이군요') |
100 |
NULLIF(100, 100) |
NULL |
IFNULL(200, 100) |
200 |
= NULL은 항상 실패하므로 반드시 이걸 써야 함조건 ? 참 : 거짓 문법에 대응하는 개념. MySQL에선 이 역할을 IF()가 담당쿼리 결과를 그대로 보여주는 대신 "조건에 따라 다르게 보여주고 싶은" 순간이 있다. 예를 들어 재고 수량이 0이면 "품절", 아니면 "판매중"이라고 표시하고 싶을 때 애플리케이션 코드에서 매번 분기하는 대신, SQL 단계에서 IF(재고=0, '품절', '판매중')처럼 한 번에 처리할 수 있다. IF()는 인자를 정확히 3개 받는다 — 조건, 참일 때 값, 거짓일 때 값. 이 순서를 벗어나면 함수 자체가 동작하지 않는다.
이 흐름을 반대로 조건이 참(TRUE)이었다면 두 번째 인자인 '참이다'가 그대로 반환됐을 것이다. IF()는 딱 이 두 갈래 외에는 다른 경로가 없다는 점이 핵심이다 — "세 번째, 네 번째 조건"은 애초에 존재하지 않는다.
테이블에는 값이 채워지지 않은 컬럼, 즉 NULL이 흔하다. 예를 들어 고객 테이블의 '별명' 컬럼이 비어있으면 화면에 그냥 빈칸이 뜨거나 "NULL"이라는 문자열이 그대로 노출돼 사용자에게 어색하게 보인다. IFNULL(별명, '이름 없음')처럼 감싸두면, 값이 있으면 그 값을, NULL이면 지정한 기본값을 안전하게 대신 보여줄 수 있다. IFNULL은 인자를 2개만 받는다는 점에서 IF()와 헷갈리기 쉬우니 주의한다.
NULLIF는 IFNULL과 방향이 정반대다. IFNULL은 "NULL을 없애는" 함수라면, NULLIF는 "특정 조건에서 일부러 NULL을 만드는" 함수다. NULLIF(A, B)는 A와 B가 같으면 NULL을, 다르면 A를 그대로 반환한다. 대표적인 활용은 나눗셈에서 분모가 0이 되는 상황을 막는 것이다. 매출 / NULLIF(방문자수, 0)처럼 쓰면 방문자수가 0일 때 분모가 그대로 0이 되어 에러가 나는 대신 결과가 NULL로 처리돼 안전하게 넘어간다.
NULL은 0도, 빈 문자열도 아닌 "값이 없다"는 상태 그 자체다. 그래서 WHERE 컬럼 = NULL처럼 등호로 비교하면 SQL 엔진 입장에서는 "알 수 없는 것과 알 수 없는 것을 비교"하는 셈이라 항상 결과가 거짓(정확히는 UNKNOWN)으로 처리되어 단 한 행도 조회되지 않는다. NULL 여부를 검사할 땐 반드시 IS NULL / IS NOT NULL을 써야 한다. IF·IFNULL·NULLIF 세 함수 모두 이 NULL의 특수성을 다루기 위해 존재한다고 봐도 된다.
| 연산식 | 결과 | 이유 |
|---|---|---|
NULL = NULL |
NULL (UNKNOWN) | 같은 "알 수 없음"끼리도 참/거짓을 단정할 수 없다 |
NULL + 1 |
NULL | 값이 없는 것에 숫자를 더해도 여전히 값이 없다 |
NULL = 0 |
NULL (UNKNOWN) | NULL은 0이 아니라 "값 자체가 없음"이므로 비교가 성립하지 않는다 |
IFNULL(NULL, 0) = 0 |
참(TRUE) | IFNULL로 먼저 NULL을 0으로 바꿔야 비로소 정상 비교가 된다 |
IF()는 조건이 딱 하나일 때 짧게 쓰기 좋고, CASE WHEN은 조건이 여러 개로 늘어날 때 훨씬 읽기 편하다. IF를 중첩해서 IF(a, x, IF(b, y, z))처럼 쓰면 조건이 3개만 넘어가도 괄호가 겹쳐 읽기 어려워진다. 이럴 땐 CASE WHEN a THEN x WHEN b THEN y ELSE z END로 풀어 쓰는 편이 유지보수에 유리하다.
IFNULL은 인자를 정확히 2개만 받는다. 하지만 실무 데이터는 "이 값이 없으면 저 값, 저 값도 없으면 그 다음 값"처럼 대체값 후보가 여러 단계로 이어지는 경우가 많다. 이럴 때는 COALESCE(A, B, C, ...)처럼 인자를 원하는 만큼 나열해, 앞에서부터 NULL이 아닌 첫 값을 찾아낸다. COALESCE는 표준 SQL 함수라 다른 DB(Oracle, PostgreSQL 등)에서도 동일하게 쓰이므로, 여러 DB를 넘나드는 코드라면 COALESCE 쪽이 더 호환성 있다.
실제 리포트 쿼리에서는 IF·IFNULL·NULLIF가 한 문장 안에 섞여 등장하는 일이 흔하다. 대표적으로 "전환율 = 구매건수 / 방문건수"를 구할 때 방문건수가 0이면 0으로 나누는 에러가 나므로, NULLIF로 분모를 먼저 방어하고 IFNULL로 최종 결과의 NULL을 0으로 다시 채우는 이중 방어를 쓴다.
- 나눗셈 쿼리를 짤 땐 분모에 NULLIF(분모, 0)을 습관적으로 붙인다
- 화면에 보여줄 값은 IFNULL로 사용자 친화적인 기본값으로 마무리한다
- 조건이 3개 이상이면 IF 중첩 대신 CASE WHEN으로 바꾼다
| 실수 | 증상 | 해결 |
|---|---|---|
| IFNULL에 조건 3개를 넣으려고 시도 (IF와 혼동) | "Incorrect parameter count" 에러 발생 | 조건 분기가 필요하면 IF(조건,참,거짓)을 사용한다 |
| WHERE 컬럼 = NULL로 NULL 검사 | 항상 결과가 0행으로 나옴 | WHERE 컬럼 IS NULL / IS NOT NULL 사용 |
| NULLIF(A,B)를 "다르면 NULL"로 반대로 암기 | 조건 로직이 뒤바뀌어 의도와 반대로 동작 | "같으면 NULL, 다르면 A"라는 원래 규칙 재확인 |
| IFNULL(A,B)에서 대체값 B도 NULL일 수 있음을 간과 | 여전히 NULL이 나와 화면에 빈칸 노출 | COALESCE(A,B,C,...)로 대체값 후보를 여러 단계로 준비 |
| 나눗셈 전에 NULLIF로 분모 방어를 하지 않음 | 분모가 0일 때 Division by zero 경고 또는 예기치 않은 결과 | 분모 자리에 NULLIF(분모, 0)을 습관적으로 적용 |
NULL 처리 함수는 아무 곳에나 감싸면 되는 기능이 아니다. 원본 데이터의 의미를 보존할지, 계산 중 에러를 막을지, 화면에 보여줄 값을 정리할지에 따라 적용 위치가 달라진다.
핵심 한 줄 요약
Tags
'php' 카테고리의 다른 글
| MySQL PAD · TRIM — 패딩·공백 제거 완전 정리 (0) | 2026.06.27 |
|---|---|
| MySQL CASE WHEN — 다중 조건 분기 완전 정리 (0) | 2026.06.27 |
| MySQL CONCAT — 문자열 연결 완전 정리 (0) | 2026.06.27 |
| MySQL SET 변수 · PREPARE — 동적 쿼리 완전 정리 (0) | 2026.06.27 |
| MySQL CTE WITH — 공통 테이블 식 완전 정리 (0) | 2026.06.27 |
왕진 블로그

댓글