今天给大家分享一下我自己和身边人摔过的跤,来看看这几个“易错知识点”,你中过招没?
1. NULL值:它不是“0”或“空字符串”,是“未知”
这大概是所有SQL初学者的第一个噩梦。NULL不等于零,也不等于空字符串,它表示“未知”。所以,用 去判断NULL,基本是白费力气。=
-- 错误示范:这样查不出任何结果
SELECT * FROM Employees
WHERE ManagerId = NULL;
-- 正确姿势:使用 IS NULL 或 IS NOT NULL
SELECT * FROM Employees
WHERE ManagerId IS NULL;
-- 另一个常见坑:任何与NULL的运算,结果还是NULL
SELECT 10 + NULL; -- 结果是 NULL
SELECT 'Hello ' + NULL; -- 结果还是 NULL
想象一下,你要算团队平均奖金,如果有人奖金是NULL,你没处理,整个平均值可能就废了。
-- 假设Bonus列有NULL值
SELECT AVG(Bonus) FROM Employees; -- 结果可能不准,因为NULL不参与运算
SELECT AVG(ISNULL(Bonus, 0)) FROM Employees; -- 先用ISNULL把NULL转成0再算
2. 在WHERE子句里对字段做计算
这个坑性能损耗极大。当你对表字段使用函数或者运算时,SQL很可能就无法使用索引了,导致全表扫描。
-- 错误示范:假设CreateTime字段有索引
SELECT * FROM Orders
WHERE YEAR(CreateTime) = 2023;
-- 正确姿势:让计算发生在等式的另一边,保持字段“干净”
SELECT * FROM Orders
WHERE CreateTime >= '2023-01-01' AND CreateTime < '2024-01-01';
上面两句结果一样,但下面那句能命中索引,查询速度天差地别。记住,要把字段当“祖宗”一样供着,尽量别对它动手动脚。
3. JOIN 和 WHERE 的过滤顺序
很多人以为LEFT JOIN(左连接)时,条件写在ON里和写在WHERE里是一样的。大错特错!
-- 场景:找出所有员工,以及他们的部门名(即使没有部门也显示)
-- 假设我们只想看‘技术部’的员工,但其他部门的员工也要显示为NULL
-- 错误写法:这样写,LEFT JOIN 实际上变成了 INNER JOIN
SELECT e.Name, d.DepartmentName
FROM Employees e
LEFT JOIN Departments d ON e.DepartmentId = d.Id
WHERE d.DepartmentName = '技术部'; -- WHERE子句会过滤掉部门为NULL的行!
-- 正确写法:把针对右表的过滤条件放在ON里
SELECT e.Name, d.DepartmentName
FROM Employees e
LEFT JOIN Departments d ON e.DepartmentId = d.Id AND d.DepartmentName = '技术部';
简单记:ON是连接前过滤,WHERE是连接后过滤。对于LEFT JOIN,放在ON里能保住左表的所有记录,放在WHERE里就可能“误杀”。
4. COUNT(*) 和 COUNT(字段名) 的区别
这俩兄弟看着像,脾气可不一样。
-- 统计表中有多少条记录
SELECT COUNT(*) FROM Employees; -- 计算所有行的数量,不管列里是不是NULL
-- 统计某个字段非空值的数量
SELECT COUNT(ManagerId) FROM Employees; -- 只计算 ManagerId 不是 NULL 的行
所以,如果你的字段允许为NULL, COUNT(字段名)的结果很可能就小于 COUNT(*)。 用的时候得心里有数。
5. 字符串比较的大小写和空格
SQL的默认设置下,字符串比较是不区分大小写的,但这依赖于你的数据库排序规则(Collation)。有时候你觉得它该区分,它却不区分,很让人困惑。
-- 在默认不区分大小写的数据库里,这个查询会返回 'apple', 'APPLE', 'Apple' 所有行
SELECT * FROM Fruits WHERE Name = 'apple';
-- 如果你真想精确匹配大小写,可以这样做:
SELECT * FROM Fruits WHERE Name = 'apple' COLLATE SQL_Latin1_General_CP1_CS_AS; -- CS表示Case Sensitive(区分大小写)
另外,结尾的空格也经常被忽略。
-- ‘Hello’ 和 ‘Hello ’(后面有个空格)在比较时很可能被认为是相等的。
最后说一句
这些知识点单拎出来看都不难,但混在复杂的业务逻辑里,一不小心就会成为隐蔽的bug。 我自己的经验是,多写多错,多错多记,下次下笔之前,心里先打个问号:“这里有没有我熟悉的坑?”
扎实的基础,往往就体现在对这些细节的处理上。 共勉!
该文章在 2025/11/6 15:14:40 编辑过