LOGO 首页 OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 技术文档 其他文档  
 
网站管理员

SQL Server 跑出 0 行结果,逻辑却没问题?这6个坑,99% 的人都踩过

admin
2026年6月5日 9:22 本文热度 49

你写的 SQL 跑出来 0 行结果,但逻辑明明没问题——99% 的情况,是 NULL 在作怪。今天把 SQL Server 开发中最高频的 10 个坑,一次性全部讲清楚。

引言

生产事故往往不是复杂逻辑写错了。

是一个 NULL,一个隐式转换,一个忘记加 ORDER BY。

在 SQL Server 里,有些行为和直觉完全相反。你以为 NOT IN 能过滤数据,结果返回空。你以为日期比较没问题,结果漏了时间部分。你以为 COUNT(列名) 和 COUNT(*) 一样,结果差了几千行。

这篇文章,把 10 个最容易翻车的场景整理出来。每一个都附有反例和正确写法,直接收藏备用。


坑 1:NOT IN 里有 NULL,结果永远是空

这是 SQL Server 里最经典、危害最大的陷阱。

看这个场景:找出不在黑名单里的用户。

-- 看似没问题
SELECT user_id
FROM users
WHERE user_id NOT IN (
    SELECT blocked_user_id FROM blacklist
);

如果 blacklist 里 blocked_user_id 有哪怕一行 NULL,这个查询返回 0 行。

原因NOT IN 等价于 <> value1 AND <> value2 AND ... AND <> NULL。而任何值与 NULL 比较,结果都是 UNKNOWN(不是 TRUE,也不是 FALSE)。整个 AND 链只要有一个 UNKNOWN,最终结果就是空。

正确写法——改用 NOT EXISTS:

SELECT user_id
FROM users u
WHERE NOT EXISTS (
    SELECT 1 FROM blacklist b
    WHERE b.blocked_user_id = u.user_id
);

NOT EXISTS 天然忽略 NULL 行,安全可靠。

铁律:子查询结果可能含 NULL 时,禁用 NOT IN,改用 NOT EXISTS


坑 2:NULL 参与运算,结果还是 NULL

这个坑更隐蔽,不会报错,只会悄悄给你错误数据。

-- 假设 discount 列有些行是 NULL
SELECT order_id,
       amount + discount AS final_amount   -- 这里有问题!
FROM orders;

当 discount 为 NULL 时,amount + NULL = NULL,不是 amount

同样,字符串拼接也一样:

-- 用户名或姓氏为 NULL,整个结果就是 NULL
SELECT first_name + ' ' + last_name AS full_name
FROM users;

正确写法——用 ISNULL 或 COALESCE 兜底:

SELECT order_id,
       amount + ISNULL(discount, 0AS final_amount
FROM orders;

SELECT ISNULL(first_name, ''+ ' ' + ISNULL(last_name, ''AS full_name
FROM users;

铁律:字段参与计算或拼接前,先处理 NULL。


坑 3:COUNT(列名) 会跳过 NULL

COUNT(*) 统计行数。COUNT(列名) 统计该列非 NULL 的行数

-- 假设 orders 有 100 行,remark 列有 30 行是 NULL
SELECT COUNT(*)       -- 返回 100
     , COUNT(remark)  -- 返回 70!
FROM orders;

这两个数字不一样!

很多人用 COUNT(某列) 来统计业务量,如果这列有 NULL,数字就会偏小,而且不会有任何提示。

明确你的意图:

-- 统计总行数
COUNT(*)

-- 统计某列填写了值的行数
COUNT(列名)

-- 统计去重后的非 NULL 值个数
COUNT(DISTINCT 列名)

铁律:统计行数用 COUNT(*),统计有效填写数才用 COUNT(列名),两者含义不同。


坑 4:BETWEEN 日期,时间部分被忽略

这个坑在查当天数据时极其常见。

-- 想查 2026-06-01 当天的订单
SELECT * FROM orders
WHERE order_time BETWEEN '2026-06-01' AND '2026-06-01';

问题'2026-06-01' 在 SQL Server 里默认是 2026-06-01 00:00:00.000

结果:只会查到恰好在 00:00:00 这一刻的记录,整天的数据几乎全部漏掉。

正确写法:

-- 方式 1:右边用下一天
WHERE order_time >= '2026-06-01'
  AND order_time  < '2026-06-02'

-- 方式 2:用 CAST 截断时间部分
WHERE CAST(order_time AS DATE= '2026-06-01'

方式 1 更推荐,因为 CAST(order_time AS DATE) 会让索引失效(对列做了函数操作)。

铁律:日期范围查询,右端点用 < 下一天,不要用 BETWEEN


坑 5:TOP 不加 ORDER BY,结果不确定

-- 取最新 10 笔订单?错了!
SELECT TOP 10 * FROM orders;

没有 ORDER BY 的情况下,TOP 返回的是引擎扫描时碰到的前 N 行,顺序取决于存储结构和执行计划,每次执行都可能不同

这在开发环境通常没问题(数据少,顺序相对稳定),但上线后数据量大、碎片化,结果就乱了

正确写法:

SELECT TOP 10 *
FROM orders
ORDER BY create_time DESC;

铁律TOP 必须配 ORDER BY,否则结果无意义。


坑 6:字符串比较大小写,结果因排序规则而异

在 SQL Server 中,字符串比较是否区分大小写,取决于数据库的排序规则(Collation)

-- 在 Chinese_PRC_CI_AS(不区分大小写)排序规则下:
WHERE username = 'Admin'   -- 能查到 'admin'、'ADMIN'、'Admin'

-- 在 Latin1_General_CS_AS(区分大小写)排序规则下:
WHERE username = 'Admin'   -- 只能查到 'Admin',查不到 'admin'

CI = Case Insensitive(不区分大小写),CS = Case Sensitive(区分大小写)。

大多数 SQL Server 默认是 CI(不区分大小写),但如果你的代码迁移到另一个数据库实例,行为可能突然变了。

如果需要明确控制,用 COLLATE:

-- 强制区分大小写的比较
WHERE username COLLATE Latin1_General_CS_AS = 'Admin'

-- 强制不区分大小写的比较
WHERE username COLLATE Chinese_PRC_CI_AS = 'Admin'

铁律:跨环境部署的系统,不要依赖默认排序规则,显式指定 COLLATE 或在文档中记录排序规则假设。


一张速查表

症状
正确做法
NOT IN
 含 NULL
返回 0 行
改用 NOT EXISTS
NULL 参与计算
结果意外为 NULL
用 ISNULL/COALESCE 兜底
COUNT(列名)
比预期少
统计行数用 COUNT(*)
BETWEEN
 日期
漏掉时间部分
改用 >= 当天 AND < 次日
TOP
 无 ORDER BY
结果不确定
TOP
 必须配 ORDER BY
排序规则不一致
大小写行为不同
显式指定 COLLATE

写在最后

SQL Server 的这些坑,不是语言设计缺陷,是严格遵守 SQL 标准的结果

NULL 的三值逻辑(TRUE / FALSE / UNKNOWN)在 ANSI SQL 规范里写得清清楚楚,只是大多数人学 SQL 时没人告诉过他们。

好消息是:踩一次就记住了。坏消息是:踩在生产环境代价很大

所以把这张速查表收藏起来。下次写 SQL 之前,对着扫一眼——可能省掉一个深夜的故障排查。


该文章在 2026/6/5 16:18:46 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved  粤ICP备13012886号-2  粤公网安备44030602007207号