参数校验必须前置:SQL Server 按类型区分判空,PostgreSQL 用 RAISE EXCEPTION 拦截超长字符串,MySQL 需处理大小写敏感,Oracle 用正则 + 范围双检日期,所有校验须在事务 BEGIN 后、DML 前执行。

SQL Server 存储过程中怎么安全地校验 @input_id 是否为空或非法
直接用 IS NULL 或 = '' 判断不够,因为 @input_id 可能是 INT 类型,空字符串会触发隐式转换错误;也可能是 VARCHAR 但含空白符。必须先明确类型再选校验方式。
- 如果是
INT参数:只判IS NULL,别碰=''或LEN(),否则报错Conversion failed when converting the varchar value'' to data type int. - 如果是
VARCHAR参数:用NULLIF(LTRIM(RTRIM(@input_name)), '') IS NULL,一步干掉空、全空格、NULL - 校验失败立刻
RETURN,别等后续逻辑出错才中断——避免无意义的表扫描或事务开销
PostgreSQL 存储过程里如何提前拦截超长字符串参数(比如 @desc 超过 500 字符)
PostgreSQL 的 PROCEDURE 或 FUNCTION 不像 SQL Server 那样支持 RAISERROR,得用 RAISE EXCEPTION 主动终止,并且要在参数被插入或更新前做检查。
- 别在
INSERT INTO …… VALUES (@desc)之后才查长度,DDL 约束(如CHARACTER VARYING(500))虽能兜底,但报错信息不友好,堆栈也不指向你的校验逻辑 - 写成:
IF LENGTH(COALESCE(@desc, '')) > 500 THEN RAISE EXCEPTION'param @desc exceeds 500 chars'; END IF; - 注意
COALESCE必须包住@desc,否则LENGTH(NULL)返回NULL,条件判断失效
MySQL 存储过程中对 @status 做枚举值预判为什么总漏掉 ‘pending’ 和 ‘PENDING’
大小写敏感性是坑源。MySQL 默认用 utf8mb4_0900_as_cs 或类似排序规则时,'pending' ≠ 'PENDING',但开发者常按“业务语义”想当然忽略。
- 别写
@status NOT IN ('active', 'inactive')这种漏判逻辑,要显式列出所有合法值:NOT IN ('active', 'inactive', 'pending', 'PENDING', 'Pending') - 更稳妥的是统一转小写再比:
LOWER(@status) NOT IN ('active', 'inactive', 'pending'),前提是业务允许忽略大小写 - 如果数据库列定义了
CHECK约束,存储过程里仍要校验——约束只拦 DML,拦不住你在过程里拼 SQL 字符串再EXECUTE IMMEDIATE
Oracle PL/SQL 中验证 p_date 是有效日期却总被 TO_DATE 异常打断流程
TO_DATE(p_date, 'YYYY-MM-DD') 一遇到非法格式就抛 ORA-01843: not a valid month,没法继续走正常逻辑。不能靠外层异常捕获来“补救”,得前置过滤。
- 用
REGEXP_LIKE(p_date, '^d{4}-d{2}-d{2}$')先筛格式,再进TO_DATE——正则快且不抛错 - 别省略年份范围检查,比如
'9999-99-99'过得了正则,但TO_DATE仍失败;加一层SUBSTR(p_date, 1, 4) BETWEEN '1900' AND '2100' - 如果参数本就是
DATE类型,就根本不用解析——说明调用方传错了类型,该改应用层,不是过程里硬扛
最易被忽略的点:所有预判逻辑都得放在事务 BEGIN 之后、实际 DML 之前;否则校验通过了,但事务已启,回滚成本高,还可能干扰调用方的错误分类。参数校验不是锦上添花,是隔离风险的第一道门。