RETURN值必须用EXEC @var = proc语法显式捕获,仅返回整数,用于流程控制;OUTPUT参数需声明为OUTPUT关键字,用于返回数据;二者用途不同且可共存。

SQL Server 存储过程的 RETURN 值不是结果集,也不是 OUTPUT 参数,它必须显式捕获到变量里才能用;漏掉这一步,你永远拿不到状态码。
RETURN 语句只返回整数,且必须用变量接收
RETURN 后面只能跟一个整数表达式,比如 RETURN 0、RETURN @err_code。它不返回数据行,也不传回字符串或 NULL —— 这点和函数或 OUTPUT 参数完全不同。关键在于:调用方必须声明变量并用 EXEC @ret = proc_name 语法捕获,否则值直接丢弃。
- 正确写法:
DECLARE @ret INT; EXEC @ret = usp_CheckUserExist @id = 123; SELECT @ret; - 错误写法:
EXEC usp_CheckUserExist @id = 123;→@ret永远是 NULL,RETURN 值已丢失 - 在 SSIS 或 ADO.NET 中,需显式将参数方向设为
ReturnValue,不能当成Output类型处理
RETURN 和 OUTPUT 参数用途根本不同,别混用
RETURN 是流程控制信号,OUTPUT 是数据载体。比如验证用户是否存在,用 RETURN 表示“找到/没找到/参数错”,而用 OUTPUT 返回用户名、邮箱等实际字段。
-
RETURN 0:常规成功(不是“有数据”,只是执行没崩) -
RETURN -1:常见约定表示通用失败,但你可以自定义,比如RETURN 101表示主键冲突,RETURN 102表示外键缺失 - OUTPUT 参数必须在
CREATE PROC里声明为@name VARCHAR(50) OUTPUT,调用时也要带OUTPUT关键字,否则值不会回写 - 一个存储过程可以同时有 RETURN + 多个 OUTPUT + 结果集,三者互不干扰,但获取时机不同:结果集最先可用,OUTPUT 和 RETURN 要等所有结果集释放完才就绪
常见陷阱:@@ERROR 不能替代 RETURN,也不能跨语句保留
@@ERROR 只反映上一条语句是否出错,且下一语句一执行就覆盖。它不适合做统一状态出口,尤其在有 IF/ELSE 或事务块时极易误判。
- 错误模式:
SELECT * FROM t; IF @@ERROR 0 RETURN 5;→ 如果SELECT成功但后续 INSERT 失败,这个 RETURN 根本不会触发 - 安全做法:每条关键语句后立刻检查
@@ERROR并赋值给局部变量,最后统一RETURN @err_code - 更推荐用
TRY...CATCH:在 CATCH 块里设@err_code = ERROR_NUMBER(),再RETURN @err_code,逻辑更清晰
返回值范围建议:避开系统保留码
SQL Server 自己用 -1 到 -99 表示内部错误(如权限不足、对象不存在),你自己定义的状态码最好用正数或 ≤ -100 的负数。
- 推荐起步值:
RETURN 0(成功)、RETURN 1(参数为空)、RETURN 2(查无此记录)、RETURN 100+留给业务异常 - 避免用
RETURN -1表示“未登录”,因为客户端可能误判成“连接失败” - 如果过程里调用了其他存储过程,记得检查它的 RETURN 值并决定是否透传或转换,否则上层看不到底层错误
最常被忽略的一点:RETURN 值在多结果集场景下,要等所有 SELECT 输出都读完、IRowset::Release 完成后才真正可读——很多 ODBC 或旧版 .NET 驱动会在这里卡住或静默失败。

















