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

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

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的行 ✅

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

SUM/AVG也会忽略NULL

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;

避坑建议

  • 设计表时尽量NOT NULL + DEFAULT
  • 查询NULL用IS NULL
  • NOT IN改成NOT EXISTS
  • 用COALESCE处理NULL
posted @ 2025-10-15 15:35  boygdm  阅读(13)  评论(0)    收藏  举报