NULL参与任何运算结果均为NULL且不报错,必须用COALESCE或ISNULL提前兜底;SET赋值遇NULL即污染变量;WHERE中NULL参数需用(@param IS NULL OR col = @param)避免索引失效;字符串拼接须对每个字段COALESCE;变量需显式初始化,参数应校验NULL及空值。

直接说结论:NULL参与任何算术、字符串拼接或比较运算,结果几乎总是NULL,且不报错——它会静默污染后续所有逻辑。必须在计算发生前就用COALESCE或ISNULL兜底,而不是等出错了再查。
SET赋值时遇到NULL,结果立刻变NULL
这是最隐蔽的崩坏点:SET @total = @total + @amount只要@amount是NULL,整条语句执行完@total就变成NULL,后面再加、再比、再拼接全失效。
- 别写
IF @amount IS NULL SET @amount = 0再运算——多一步就多一个漏判风险 - 统一改用
SET @total = @total + COALESCE(@amount, 0)(跨库)或SET @total = @total + ISNULL(@amount, 0)(SQL Server专属) - 注意类型:如果
@amount是DECIMAL(10,2),COALESCE(@amount, 0)返回仍是DECIMAL(10,2);而ISNULL(@amount, 0)严格按@amount类型返回,更稳妥
WHERE里参数为NULL时,如何跳过该条件
常见于可选搜索字段,比如前端没填姓名,后端传进来的@name就是NULL。不能靠WHERE name = ISNULL(@name, name)这种写法——它表面简洁,但ISNULL(@name, name)会让SQL Server无法走索引。
- 安全模式:
WHERE (@name IS NULL OR name = @name) AND (@age IS NULL OR age = @age) - 别把
OR塞进单个表达式里,比如WHERE name = COALESCE(@name, name),同样破坏索引 - 如果参数允许为空但业务上需区分“未填”和“填了空字符串”,得额外加
LEN(ISNULL(@name, '')) > 0判断
触发器或SELECT INTO里拼接字符串,任一字段为NULL就全崩
CONCAT('ID:', id, '-', name)中只要id或name是NULL,整个结果就是NULL。这在BEFORE INSERT触发器里尤其危险,可能直接违反NOT NULL约束导致插入失败。
- 字符串拼接必须全包:
CONCAT('ID:', COALESCE(id, ''), '-', COALESCE(name, '')) -
SELECT col INTO @var FROM t WHERE id = 123查不到数据时,@var不会变NULL,而是保持旧值——必须显式初始化:SET @var = NULL再执行 - 想让子查询结果直接参与空值处理,改用
SET @var = COALESCE((SELECT col FROM t WHERE id = 123), 'default')
最易被忽略的是变量初始化和参数校验顺序:存储过程开头不集中做IF @param IS NULL THROW,后面每用一次都得重复判断;而字符串类参数若只判IS NULL,漏掉空格或''照样出错。











