MySQL中NULL值的5个反直觉行为,扭到了吗?

MySQL中NULL值的5个反直觉行为,扭到了吗?

核心原则:NULL和任何值比较(=、!=、>、<),结果都是NULL,不是TRUE也不是FALSE。

1、NULL = NULL 返回NULL
正确的NULL判断

-- ❌ 错误写法
SELECT * FROM user WHERE phone = NULL;
-- 0 rows(查不到任何数据)SELECT * FROM user WHERE phone != NULL;
-- 0 rows(也查不到任何数据)-- ✅ 正确写法
SELECT * FROM user WHERE phone IS NULL;
-- 查到phone为NULL的行 ✅SELECT * FROM user WHERE phone IS NOT NULL;
-- 查到phone不为NULL的行 ✅

2、COUNT(column)不统计NULL

INSERT INTO test_count VALUES 
(1, 'alice', '13800138000'),
(2, 'bob', NULL),
(3, 'charlie', NULL),
(4, 'david', '15000150000');-- 统计有手机号的用户数
SELECT COUNT(phone) FROM user;  -- 8(有8个用户填了手机号)-- 统计没有手机号的用户数
SELECT COUNT(*) - COUNT(phone) FROM user;  -- 2(有2个用户没填)-- 或者
SELECT COUNT(*) FROM user WHERE phone IS NULL;  -- 2

3、SUM/AVG也会忽略NULL
4、NOT IN遇到NULL全军覆没

WHERE user_id NOT IN (100, 200, NULL)

解决方案

  • 过滤掉NULL
SELECT * FROM user 
WHERE user_id NOT IN (SELECT blocked_user_id FROM blacklist WHERE blocked_user_id IS NOT NULL  -- 关键
);
  • 用NOT EXISTS(推荐)
SELECT * FROM user u
WHERE NOT EXISTS (SELECT 1 FROM blacklist b WHERE b.blocked_user_id = u.user_id
);-- NOT EXISTS不受NULL影响 ✅
  • 用LEFT JOIN
SELECT u.* 
FROM user u
LEFT JOIN blacklist b ON u.user_id = b.blocked_user_id
WHERE b.blocked_user_id IS NULL;