글을 작성하게 된 계기
MySQL에서 NULL을 비교할 때 주의해야 할 점을 알게 되었고, 이를 정리하기 위해 글을 작성하게 되었습니다.
1. IS NULL vs = NULL
MySQL에서 IS NULL 과 = NULL 은 전혀 다르게 동작합니다. 간단한 예제를 통해 이를 확인해보겠습니다.
1
2
3
4
5
6
7
8
9
10
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(100),
deleted_at DATETIME
);
INSERT INTO users (id, name, deleted_at) VALUES
(1, 'Alice', NULL),
(2, 'Bob', '2024-01-01 00:00:00'),
(3, 'Charlie', NULL);
1-1. IS NULL
IS NULL 은 NULL 값을 올바르게 비교하는 방법입니다. 이 경우 deleted_at이 NULL인 행만 정확히 조회됩니다.
1
2
3
SELECT *
FROM users
WHERE deleted_at IS NULL;
1
2
3
4
5
6
7
8
9
mysql> SELECT *
-> FROM users
-> WHERE deleted_at IS NULL;
+----+---------+------------+
| id | name | deleted_at |
+----+---------+------------+
| 1 | Alice | NULL |
| 3 | Charlie | NULL |
+----+---------+------------+
1-2. = NULL
반면 = NULL 은 항상 FALSE를 반환합니다. 이는 NULL은 값이 없음 을 의미하므로, = NULL 비교 자체가 논리적으로 의미가 없기 때문입니다.
1
2
3
SELECT *
FROM users
WHERE deleted_at = NULL;
1
2
mysql> SELECT * FROM users WHERE deleted_at = NULL;
Empty set (0.02 sec)
2. 왜 이런 결과가 나올까?
MySQL에서 NULL은 값이 없거나 알 수 없는 상태를 의미합니다. 그래서 NULL은 단순한 값이 아니라, 모른다 는 개념으로 취급됩니다. 따라서 NULL을 다른 값과 비교할 경우 그 결과도 확실하지 않기 때문에, 그 결과를 TRUE나 FALSE가 아닌 UNKNOWN 으로 처리하기 때문입니다.
이는 ISO/IEC 9075 에 정의된 비교 연산 정의에 따르면 다음과 같은 규칙이 있습니다. 두 값 중 하나라도 NULL 이면, 그 비교 결과는 UNKNOWN 이 되며, WHERE 절에서는 이 결과가 무시 되어 조건을 만족하지 않은 것과 동일하게 취급됩니다. MySQL도 이를 따랐겠죠?
1
2
Let XV and YV be two values represented by <value expression>s X and Y, respectively.
The result of:X <comp op> Y is determined as follows: If either XV or YV is the null value, then X <comp op> Y is UNKNOWN.
3. 정리
MySQL에서 NULL을 비교할 때는 IS NULL 을 사용해야 하며, = NULL 은 항상 FALSE를 반환합니다. 이는 NULL이 값이 없음을 의미하기 때문이며, ISO/IEC 9075 표준에 따라 UNKNOWN으로 처리됩니다. 왜 이 글을 작성하고 있냐면, 복잡한 쿼리 작성할 때, IS NULL 을 사용하지 않아서 꽤 많은 데이터를 잘못 보정했거든요. 💩
- ISO/IEC 9075
- Comparisons with NULL and the three-valued logic (3VL)
- [Working with NULL Values](https://dev.mysql.com/doc/refman/8.0/en/working-with-null.htm