SQL Server OUTPUT参数必须定义和调用时均显式加OUTPUT关键字;JDBC需registerOutParameter()且用execute();MyBatis须配mode="OUT";SqlDataReader后才能读取;MySQL的OUT参数必须用初始化的用户变量。

SQL Server 中 OUTPUT 参数没加 OUTPUT 关键字
定义和调用时都必须显式写 OUTPUT,缺一不可。只在定义里写了 @id INT OUTPUT,但调用时写成 EXEC usp_get @id(漏掉 OUTPUT),参数值就永远不会传出来。
常见错误包括:
- 调用时用了字面量:
EXEC usp_get 123 OUTPUT—— 常量不可写,SQL Server 直接报错 - 用了表达式:
EXEC usp_get (@a + @b) OUTPUT—— 没有内存地址可赋值 - 参数顺序错乱:定义是
@id OUTPUT, @name OUTPUT,调用却按@name OUTPUT, @id OUTPUT位置传,类型不匹配导致静默失败或截断
JDBC/MyBatis 调用时没注册 OUT 参数
不是 SQL 写错了,而是驱动层根本没告诉数据库“这个参数我要取值”。CallableStatement 必须在 execute() 前调用 registerOutParameter(),否则执行完也拿不到值。
关键点:
- 索引从 1 开始,
registerOutParameter(2, Types.INTEGER)对应第二个参数 - 不能用
executeQuery()或executeUpdate()替代execute(),否则 OUT 参数不会被填充 - MyBatis 中必须配置
mode="OUT"和jdbcType,例如: - 别依赖
ResultSet去读 OUT 参数——它根本不在结果集里
SqlDataReader 执行后拿不到 OUTPUT 值
很多封装类(比如旧版 SQLHelper)会在执行前清空参数集合:cmd.Parameters.Clear(),导致你设好的 Direction = ParameterDirection.Output 白费。
典型表现是执行完 reader.Read() 后,再取 param[2].Value 报 NullReferenceException。
解决方法:
- 确认封装类是否重置了参数;若会,改用
DataSet或手写SqlCommand调用 - 务必在
ExecuteReader()或ExecuteNonQuery()之后再读取SqlParameter.Value - 不要在 using 块外访问 reader,更不要假设 reader 关闭后参数还能读——它们生命周期无关
MySQL 的 OUT 参数传了常量或变量未初始化
MySQL 不允许把字面值传给 OUT 或 INOUT 参数。写 CALL proc_name(123, @out_val) 是错的,因为第一个参数是 IN 没问题,但第二个如果声明为 OUT,就必须是用户变量。
容易忽略的细节:
-
SET @out_val = NULL;不是可选步骤——未初始化的变量在参与计算或比较时可能引发隐式转换错误 -
存储过程体内若用
DECLARE id INT和参数名同名,会覆盖参数作用域,传进来的值直接变NULL -
SELECT ... INTO @out_val要求查询结果恰好一行一列;多行会报错,无行则@out_val保持原值(不是自动变NULL)
最常被忽略的是:OUTPUT/OUT 参数本质是变量赋值,不是数据管道。它只能传一个标量,永远装不下一行、一列或多条记录。想返结果集,该用 SELECT 就用 SELECT,别往 @json_out NVARCHAR(MAX) OUTPUT 里硬塞 JSON 字符串——调试难、性能差、还容易截断。











