쉬운 코드 님의 영상을 보고 정리한 글 입니다
1) unknown
2) unavailable/withheld
3) not applicable
어떤 값이 null로 처리된 데는 다양한 맥락이 있을 수 있다는 전제를 깔고 가야 한다.
사용자가 생일을 입력을 안 했으니 생일이 없다는 말이 아니고, "생일이 언제인지 모른다"로 보는 게 맞다. SQL은 이런 모호함을 고려하여 null을 설계했다는 점을 먼저 인지하고 넘어가야 한다.
이런 맥락에서인지, 보통 null 연산은 value = NULL
/value != NULL
이 아니라, value IS NULL
/value IS NOT NULL
이렇게 표현한다.
null까지 고려하면 주의할 점이 있다 :
👉 비교 연산 시, UNKNOWN으로 처리될 수 있다는 점이다 (UNKNOWN: 모른다. TRUE일 수도, FALSE일 수도 있다)
즉, 세가지 상태가 존재한다:
- TRUE
- FALSE
- UNKNOWN
UNKNOWN이 포함된 경우를 따져보자:
- TRUE AND UNKNOWN -> UNKNOWN
- FALSE AND UNKNOWN -> FALSE
- UNKNOWN AND UNKNOWN -> UNKNOWN
- TRUE OR UNKNOWN -> TRUE
- FALSE OR UNKNOWN -> FALSE
- UNKNOWN OR UNKNOWN -> UNKNOWN
- NOT TRUE -> FALSE
- NOT FALSE -> TRUE
- NOT UNKNOWN -> UNKNOWN
SQL의 three valued logic이 중요한 이유는, 우리가 쿼리를 작성할 때 WHERE절은 TRUE인 것에 대해서만 선택한다는 점 때문이다. 만약 null이 포함된 데이터가 존재하면 결과가 의도치않게 FALSE이거나 UNKNOWN이 나올 수 있다.
쉬운 코드 님의 예시를 차용 했습니다
SELECT D.id, D.name
FROM department AS D
WHERE D.id NOT IN (
SELECT E.dept_id
FROM employee E
WHERE E.birth_date >= '2000-01-01'
);
E.dept_id에 null이 포함되어 있다면 어떻게 동작할까 ?
null >= '2000-01-01'
의 결과는 unknown이다. 결국 WHERE 절은 v not in (..., unknown, ...)
과 같이 동작할 것이다.
v not in (v1, v2, ...)
는 v != v1
AND v != v2
...와 같기 때문에, unknown이 하나라도 포함됐을 때 아래와 같은 경우가 있을 수 있다:
3 not in (1, 3, NULL) => FALSE
3 not in (1, 2, NULL) => UNKNOWN
이런 케이스에 따라, E.dept_id이 null일 때 우리의 의도와 다르게 조건문의 결과가 FALSE, UNKNOWN이 나와서 데이터가 아예 표출되지 않을 수도 있다.
null을 고려해서 쿼리를 짠다면, 아래와 같이 개선할 수 있다:
SELECT D.id, D.name
FROM department AS D
WHERE D.id NOT IN (
SELECT E.dept_id
FROM employee E
WHERE E.birth_date >= '2000-01-01' AND E.dept_id IS NOT NULL
);
SELECT D.id, D.name
FROM department AS D
WHERE NOT EXISTS (
SELECT *
FROM employee E
WHERE E.depth_id = D.id AND E.birth_date >= '2000-01-01'
);
📍 정리하자면, 데이터가 null 허용일 때 이를 고려해서 방어적으로 쿼리를 짤 필요가 있다.
덜덜 전에는 이걸 몰라서 전혀 고려하지 못하고 사용한 듯 ,, 고백하자면 이 글은 영상 보다가 등골이 서늘해서 황급히 정리한 글 입니다 ..