存储过程需显式校验输入参数非空,避免null引发崩溃;建议开头集中用is null判断并throw抛错,字符串需防空白,调用时必须用命名参数,慎用isnull/coalesce默认值。

存储过程执行时报 NULL 值导致校验失败或崩溃
参数没传进来、前端漏填、调用方未设默认值,都会让存储过程中 @param 变成 NULL。SQL Server 不会自动报错提示“你忘了传参”,而是让后续的 WHERE、CONVERT 或拼接逻辑直接炸——比如 CONVERT(INT, NULL) 报错,或 WHERE id = @id 变成全表扫描。
实操建议:
- 所有输入参数在开头就做显式非空判断,别等用到才查
- 用
IS NULL判断,不用= NULL(后者永远返回FALSE) - 错误提示用
THROW主动抛出,带明确参数名,方便定位是哪个环节漏了
IF @user_id IS NULL
THROW 50000, '参数 @user_id 不能为空', 1;
SQL Server 存储过程里怎么安全地校验多个输入参数
一个过程常有 3–5 个输入参数,挨个写 IF ... THROW 太啰嗦,也容易漏。关键是把校验逻辑集中、可读、不干扰主流程。
实操建议:
- 把所有必填参数校验放在
BEGIN后第一块,统一风格,一眼看出哪些不能为NULL - 对字符串类参数,额外加
LEN(ISNULL(@name, '''')) = 0防空格/纯空白 - 避免在
WHERE子句里写@param IS NOT NULL AND column = @param这种写法——它会让索引失效 - 如果参数允许为空但后续有分支逻辑,用
CASE WHEN @param IS NULL THEN ... ELSE ... END显式分叉
EXEC 调用存储过程时参数名写错或顺序错导致值错位
用位置传参(EXEC proc_name 'a', 'b', 1)最危险:改参数顺序、加新参数、前端字段顺序微调,都可能让 @email 接收到 @phone 的值,而 SQL 不报类型错误,只默默存错或查错。
实操建议:
- 一律使用命名参数调用:
EXEC proc_name @user_id = 123, @status = 'active' - 在存储过程定义里,给每个参数加注释说明用途和是否必填,比如:
@order_date DATETIME NULL -- 必填,格式 YYYY-MM-DD - 测试时故意传错名(如
@user_idd),确认报错是「找不到参数」而非静默忽略 - 如果调用方是 ORM(如 Dapper),检查是否启用了
command.Parameters.Add()的命名绑定,而不是靠顺序
参数丢失后想 fallback 默认值,但 ISNULL 和 COALESCE 行为不一致
很多人用 SET @val = ISNULL(@input, 'default'),结果发现 @input 是空字符串时没触发 fallback;或者用 COALESCE(@input, 'default') 却遇到数据类型隐式转换失败。
实操建议:
-
ISNULL返回第一个参数类型,COALESCE返回最高优先级类型——如果@input是VARCHAR(10),ISNULL(@input, 'long default value')会被截断 - 需要同时处理
NULL和空字符串,写成:NULLIF(LTRIM(RTRIM(@input)), '''')再套ISNULL - 数值类参数慎用
ISNULL(@num, 0):如果业务上 0 是合法值,就别用 0 做 fallback,改用THROW强制上游补全
真正难的不是写校验,是让上下游都接受“参数必须显式声明、显式传递、显式校验”这个事实。一旦有人绕过、硬编码、写死默认值,漏洞就藏在下一次字段变更里。










