컴퓨터 공부/📗 CS

[데이터베이스] 7장 - SQL 로 데이터 조회하기! NULL 의 의미와 three-valued logic

letzgorats 2024. 1. 9. 11:39

NULL의 의미

: unknown - 알려지지 않음

: unavailable or withheld - 이용할 수 없음(공개하지 않아서)

: not applicable - 적용할 수 없음

 

→ 상황에 따라 다르게 해석된다. 그렇기 때문에 NULL 끼리의 같다, 다르다를 비교할 수가 없는 것이다.

 

예시를 살펴보자.

EMPLOYEE 테이블

 

= 을 사용해서 NULL 비교

 

=(등호)를 사용해서 NULL 비교를 하면, 아무것도 나오지 않는다. 이렇게 작성하고 "birth_date 가 NULL 인 사람이 아무도 없구나~" 라고 이해하면 안 된다. 실제로 JEFF 의 생년월일은 NULL 값을 가진다.

IS 를 사용해서 NULL 비교

 

IS 를 사용해서 NULL 값 비교를 하면 제대로 NULL 인 속성이 잘 추출된다.

반대로 값이 다른지 아닌지 표현하고 싶으면 != 대신에 'IS NOT' 을 사용해야 한다.

 


 NULL과 SQL three-valued logic

그럼, 다음과 같이 NULL 값이 있는 테이블에서 birth_date = '1996-09-05' 와 같이 특정값을 WHERE 조건에 넣어주면, NULL 값은 어떻게 비교가 되는 것일까? 뭔가 '1996-09-05'와 NULL 값은 다르니까 False 를 반환할 것이라고 생각할 수 있다.

EMPLOYEE 테이블
SELECT * FROM EMPLOYEE WHERE birth_date = '1996-09-05';

 

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 테이블에 적용한다고 생각해보자.

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번 방법으로 해결하면 아래와 같은 결과를 얻는다.

2번 방법(왼쪽) 3번 방법(오른쪽) 결과


참고자료

- 유튜브 쉬운코드

반응형