✅ NULL의 의미
: unknown - 알려지지 않음
: unavailable or withheld - 이용할 수 없음(공개하지 않아서)
: not applicable - 적용할 수 없음
→ 상황에 따라 다르게 해석된다. 그렇기 때문에 NULL 끼리의 같다, 다르다를 비교할 수가 없는 것이다.
예시를 살펴보자.
=(등호)를 사용해서 NULL 비교를 하면, 아무것도 나오지 않는다. 이렇게 작성하고 "birth_date 가 NULL 인 사람이 아무도 없구나~" 라고 이해하면 안 된다. 실제로 JEFF 의 생년월일은 NULL 값을 가진다.
IS 를 사용해서 NULL 값 비교를 하면 제대로 NULL 인 속성이 잘 추출된다.
반대로 값이 다른지 아닌지 표현하고 싶으면 != 대신에 'IS NOT' 을 사용해야 한다.
✅ NULL과 SQL three-valued logic
그럼, 다음과 같이 NULL 값이 있는 테이블에서 birth_date = '1996-09-05' 와 같이 특정값을 WHERE 조건에 넣어주면, NULL 값은 어떻게 비교가 되는 것일까? 뭔가 '1996-09-05'와 NULL 값은 다르니까 False 를 반환할 것이라고 생각할 수 있다.
SQL 에서 NUL과 비교 연산을 하게 되면, 그 결과는 UNKNOWN 이다. UNKNOWN 은 "'True' 일 수도 있고, 'False' 일 수도 있다" 라는 의미이다.
three-valued-logic 이란, 비교/논리 연산의 결과로 TRUE, FALSE, UNKNOWN 을 가진다는 뜻이다.
즉, 특정값과 NULL 과의 비교를 할 때는 어떤 연산자랑 비교를 해도 UNKNOWN 의 값을 가지게 된다. 심지어 NULL과 NULL 을 비교할 때도 UNKNOWN 이라고 처리가 된다.
이 부분이 중요한 이유는 쿼리에서는 WHERE 절의 조건의 결과가 TRUE 인 tuple 만 선택이 된다.
즉, 결과가 FALSE 이거나 UNKNOWN 이면 tuple 은 선택되지 않기 때문에, 쿼리를 작성할 때, 이 부분을 잘 염두해둬야 한다.
✅ NOT IN 사용시 주의 사항
앞서 마지막으로 짚은 부분의 예시를 설명해보겠습니다.
value NOT IN (v1,v2,v3)
와 같은 구문이 있다고 할 때, 이 구문을 풀어쓰면 아래와 같다.
v!=v1 AND v!=v2 AND v!=v3
만약, v1, v2, v3 중에 하나가 NULL 이라면 어떤 결과를 반환할까? 아래 표로 확인해보자.
NOT IN 예제 | 결과 |
3 NOT IN (1,2,4) | TRUE |
3 NOT IN (1,2,3) | FALSE |
3 NOT IN (1,3,NULL) | FALASE |
3 NOT IN (1,2,NULL) | UNKNOWN |
구문의 결과가 막연히 UNKNOWN 이 되는 것이 아니라, values 튜플에 3 이 있다면 False 를 반환하는 것을 확인할 수 있다.
즉, NULL 이 UNKNOWN 값으로 '3이 될 수도 있고 안 될 수도' 있기 때문에, 결과가 UNKNOWN 이라고 해석하면 이해가 편할 것이다.
저번에 6장에서 다음과 같은 쿼리를 짠 적이 있다. 그 때는, EMPLOYEE 테이블에 birth_date 값으로 NULL 을 가지는 직원이 없었다.
'2000년대 생이 없는 부서의 ID와 이름을 알고 싶다'
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'
);
이 쿼리를 이번에는 해당 EMPLOYEE 테이블에 적용한다고 생각해보자.
현재 'JULIA' 는 2003년생으로 아직 부서를 배치받지 못했다. 즉, dept_id 가 현재 NULL 인 상태인 셈이다.
해당 쿼리에서 Department.id 가 어떤 값이 오더라도, 서브쿼리의 결과를 포함한 WHERE 조건절의 결과는 UNKNOWN 이 되거나 FALSE 가 된다. 지금 'JULIA' 의 부서가 1001인지, 1002인지, 1003인지, 1004인지, 1005인지 알려지지 않았기 때문에, 판별을 제대로 할 수가 없는 것이다.
즉, WHERE 절은 TRUE 인 경우에만 선택을 하게 된다고 했는데, 여기서 부서id 가 아직 NULL 이기 때문에, 결과적으로 TRUE 는 나올 수 없게 된다. 결국 결과는 아무것도 반환하지 않게 된다.
이 부분을 해결하기 위해서는
1) 애초에, EMPLOYEE 테이블에서 dept_id 가 NULL 값을 가질 수 없도록 NOT NULL 제약 조건을 거는 방법
2) 서브쿼리의 WHERE 절에 dept_id 가 NOT NULL 인 조건을 추가해주는 방법
3) NOT IN 을 NOT EXISTS 로 바꿔서 처리해주는 방법
으로 해결할 수 있다. 2번 방법과 3번 방법으로 해결하면 아래와 같은 결과를 얻는다.
참고자료
- 유튜브 쉬운코드
'컴퓨터 공부 > 📗 CS' 카테고리의 다른 글
[데이터베이스] 9장 - SQL 로 데이터 조회하기! Group by, Aggregation function, Order by (0) | 2024.01.11 |
---|---|
[데이터베이스] 8장 - SQL 로 데이터 조회하기! JOIN (4) | 2024.01.09 |
[데이터베이스] 6장 - SQL 로 데이터 조회하기! SubQuery, IN, EXISTS, ANY, ALL (4) | 2024.01.05 |
[데이터베이스] 5장 - SQL 로 데이터 조회하기! SELECT 를 활용해서 데이터를 읽어오는 기본적인 문법과 관련 키워드들 (4) | 2024.01.04 |
[데이터베이스] 4장 - SQL로 DB에 데이터를 추가(insert)하고 수정(update)하고 삭제(delete)하는 방법 (4) | 2024.01.02 |