必须在存储过程开头集中校验参数,sql server用throw、mysql用signal、postgresql用raise exception,数值型判is null,字符串需加trim,各库均须避免隐式转换、全表扫描或静默错误。

必须在存储过程开头集中校验,不能等用到才查;否则 NULL 可能触发隐式转换报错、全表扫描或静默写入错误数据。
SQL Server 里怎么用 THROW 做参数非空校验
只在 BEGIN 后第一块写,确保没执行任何写操作前就退出。数值型参数用 IS NULL 判断就够了;字符串得加 LTRIM(RTRIM(@name)) = '' 防空白。
IF @user_id IS NULL THROW 50000, '参数 @user_id 不能为空', 1;IF @name IS NULL OR LTRIM(RTRIM(@name)) = '' THROW 50000, '参数 @name 不能为空或仅含空白', 1;- 别对
INT类型写= '',会触发Conversion failed when converting the varchar value '' to data type int - 每个参数单独写
IF块,错误消息带参数名,方便定位是哪个漏传
MySQL 存储过程怎么让校验失败真报错
SIGNAL SQLSTATE '45000' 是唯一可靠方式。用 SELECT 或 LEAVE 都不算错误,应用层收不到异常信号。
IF @email IS NULL OR TRIM(@email) = '' THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'email 不能为空'; END IF;-
SIGNAL必须直接写在存储过程体里,不能藏在INSERT SELECT或子查询中 -
MESSAGE_TEXT控制在 128 字符内,避免被截断 - 别用
'HY000'这类系统保留码,客户端难区分是业务错还是数据库崩了
PostgreSQL 函数里怎么中断执行并提示
用 RAISE EXCEPTION,不是 RAISE NOTICE。后者只是打日志,函数照常返回、数据照常入库。
IF $1 IS NULL OR trim($1) = '' THEN RAISE EXCEPTION 'param1 cannot be null or empty'; END IF;- 位置参数引用(如
$1)比命名参数更稳,不会因重命名失效 - 拼提示信息时别直接连用户输入,用
USING HINT = 'got: ' || coalesce($1, 'NULL')防 SQL 注入 - 加
STRICT属性可自动拦截 NULL,但没法自定义错误消息,适合简单场景
跨库迁移最容易翻车的点不是语法写错,而是语义惯性:比如习惯写 IS NULL OR @p = '',到 PostgreSQL 就漏掉 trim(),到 MySQL 就忘了 SIGNAL——校验逻辑一旦松动,NULL 和空格就会一路穿透到 INSERT 里。











