sql server中用throw做参数校验,必须置于begin后首块、未执行任何写操作前;语法为throw 50000, '参数@user_id不能为空', 1,数值型只判is null,字符串用is null or ltrim(rtrim(@name)) = ''。

SQL Server 里怎么用 THROW 做参数校验
直接用 THROW,别绕路写 RAISERROR。SQL Server 2012+ 支持 THROW,它能中止当前批处理,且语法更干净——THROW 50000, '参数 @user_id 不能为空', 1 就完事。
常见错误是把校验塞在业务逻辑中间,比如 UPDATE 之后才检查;必须放在 BEGIN 后第一块,确保没执行任何写操作前就退出。
- 数值型参数只判
IS NULL,别写= '',否则触发隐式转换报错:Conversion failed when converting the varchar value '' to data type int - 字符串参数用
IS NULL OR LTRIM(RTRIM(@name)) = '',LEN(ISNULL(@name, '')) = 0也行,但注意LEN(NULL)返回NULL,条件永远不成立 - 多个参数校验别堆成一个超长 IF,每个参数单独 IF 块,错误消息带参数名,方便定位
MySQL 存储过程怎么让校验失败真报错
SIGNAL SQLSTATE '45000' 是唯一可靠方式。MySQL 不支持 THROW,SELECT 'error' 或 LEAVE 都不算错误,应用层收不到异常信号。
关键点在于:SIGNAL 必须出现在存储过程体里,不能藏在子查询或 INSERT SELECT 中——MySQL 明确禁止。
- 字符串校验写成:
IF @email IS NULL OR TRIM(@email) = '' THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'email 不能为空'; END IF; - 数值校验直接
IF @amount IS NULL THEN ...,别对 INT 字段做= '' - MESSAGE_TEXT 控制在 128 字符内,避免被截断;别用
'HY000'这类系统保留码,客户端难区分是业务错还是数据库崩了
PostgreSQL 函数里怎么中断执行并提示
用 RAISE EXCEPTION,不是 RAISE NOTICE。后者只是打日志,函数照常返回、数据照常入库。
函数默认不自动回滚,所以校验失败必须靠异常触发事务边界控制——要么整个函数加 BEGIN ... EXCEPTION 块,要么调用方显式开事务。
- 位置参数引用写法更稳:
IF $1 IS NULL OR trim($1) = '' THEN RAISE EXCEPTION 'param1 cannot be null or empty'; END IF; - 拼提示信息时别直接连用户输入:
USING HINT = 'got: ' || coalesce($1, 'NULL'),防 SQL 注入 - 加
STRICT属性(如CREATE FUNCTION f(text) RETURNS text STRICT)可自动拦截 NULL,但没法自定义错误消息,适合简单场景
跨库迁移时参数校验最容易翻车的点
不是语法差异,而是语义惯性。开发习惯写 IS NULL OR @p = '',到 PostgreSQL 就漏掉 trim(),到 MySQL 就忘了 SIGNAL 必须手动写。
更隐蔽的是 NULL 来源:前端没传、EXEC 调用省略参数、甚至 ORM 没绑定字段,都会让参数变成 NULL。而不同数据库对未传参的默认行为也不一致。
- SQL Server 的
LEN(NULL)返回NULL,MySQL 的LENGTH(NULL)也返回NULL,但 PostgreSQL 的length(NULL)报错 - Oracle 要用
IF @p IS NULL THEN RAISE_APPLICATION_ERROR(-20001, 'xxx');,没SIGNAL也没THROW - 所有数据库里,空字符串
''和NULL都不是一回事,合并判断必须显式写全,不能只靠一个条件











