1. 问题现象与背景分析
最近在优化一个老项目的订单查询功能时,遇到了一个典型的SQL Server查询陷阱。系统中有个订单表(Order),其中包含parentid字段表示上级关联订单,大多数记录该字段为NULL值(因为大部分订单没有上级关联)。同时还有order_no、customer_name等多个需要支持模糊查询的字段。开发人员编写了如下查询语句:
sql复制SELECT * FROM Order
WHERE order_no LIKE '%123%'
OR customer_name LIKE '%张%'
OR parentid LIKE '%456%'
当parentid为NULL时,整个查询条件神奇地失效了——即使order_no或customer_name明明有匹配的记录,结果集却返回空。这个现象在SQL Server 2008 R2到2019的各版本中均有出现。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. NULL值在SQL中的特殊性质
2.1 三值逻辑与NULL的本质
SQL中的NULL不是空字符串也不是0,它表示"未知"或"不存在"的概念。在逻辑运算中,SQL使用三值逻辑(TRUE/FALSE/UNKNOWN),这与大多数编程语言的二值逻辑有本质区别。当任何操作数与NULL比较时,结果都是UNKNOWN。
sql复制-- 以下表达式结果均为UNKNOWN
SELECT NULL = NULL, NULL > 5, NULL LIKE '%pattern%'
2.2 OR运算中的NULL陷阱
在三值逻辑中,OR运算的真值表如下:
| A | B | A OR B |
|---|---|---|
| TRUE | TRUE | TRUE |
| TRUE | FALSE | TRUE |
| TRUE | NULL | TRUE |
| FALSE | TRUE | TRUE |
| FALSE | FALSE | FALSE |
| FALSE | NULL | NULL |
| NULL | TRUE | TRUE |
| NULL | FALSE | NULL |
| NULL | NULL |
