CREATE PROCEDURE 是创建带输出参数存储过程的唯一标准语法,必须显式声明 OUTPUT 关键字,调用时需用已声明变量绑定并正确注册序号,SET NOCOUNT ON 推荐启用以避免客户端异常。

CREATE PROCEDURE 是创建带输出参数的存储过程的唯一标准语法,没有替代写法。必须显式声明 OUTPUT 关键字,否则参数只会被当作普通输入参数处理。
输出参数必须用 OUTPUT 显式声明
SQL Server 不会根据变量名或上下文自动识别输出意图。哪怕你只打算在过程里给某个参数赋值并希望外部读取,也必须在定义时加上 OUTPUT 标识。
常见错误是漏写 OUTPUT,导致调用方收不到值,但又不报错——只是 @result 始终为 NULL 或默认值。
-
@param_name datatype OUTPUT—— 正确写法 -
@param_name datatype = default—— 即使有默认值,也不代表它是输出参数 - 输出参数可以同时是输入参数(即
IN OUT),但 SQL Server 不支持INOUT关键字,需写成@param datatype = default OUTPUT
调用时必须用 EXEC + 变量绑定,不能直接传字面量
输出参数本质是“引用传递”,调用时必须提供一个已声明的变量来接收返回值。直接写 EXEC usp_get_id 123, 0 这类字面量调用会失败或静默忽略输出。
正确做法是先 DECLARE 变量,再 EXEC 并用 = @var OUTPUT 绑定:
DECLARE @mgr_id INT; EXEC GetImmediateManager @employeeID = 123, @managerID = @mgr_id OUTPUT; SELECT @mgr_id AS manager_id;
注意:SQL Server 允许按名传参(如 @employeeID = 123),推荐使用,避免位置错乱;但 OUTPUT 标志必须紧跟在变量名后,不能省略。
SET NOCOUNT ON 不影响输出参数,但能减少干扰
输出参数的值传递与结果集、消息行数无关。SET NOCOUNT ON 只是抑制 (1 row affected) 类消息,防止客户端误将这些消息当作结果集解析。它对 OUTPUT 参数的赋值和返回完全无影响,但强烈建议加上——尤其当过程内部有 INSERT/UPDATE/DELETE 时。
- 没加
SET NOCOUNT ON:JDBC/.NET 客户端可能因收到多条消息而抛出异常 - 加了之后:只返回你明确
SELECT或OUTPUT的内容 - 该语句应放在
AS BEGIN后第一行
JDBC 调用时 registerOutParameter 必须匹配序号或名称
Java 端用 CallableStatement 调用时,registerOutParameter 的参数序号是从 1 开始计的,且严格按 {call proc(?, ?)} 中问号顺序排列,和声明顺序一致,和命名无关。
例如 {call GetImmediateManager(?, ?)} 中第一个 ? 是 @employeeID(输入),第二个是 @managerID(输出),那么注册必须是:
cs.registerOutParameter(2, Types.INTEGER); // 第二个问号,对应 @managerID
容易踩的坑:
- 把输出参数序号写成 1(误以为是第一个声明的参数)
- 用了命名注册(
cs.registerOutParameter("@managerID", ...))但驱动版本不支持(旧版 JDBC 驱动仅支持序号) - 试图用
CURSOR或TIMESTAMP作输出参数——SQL Server JDBC 明确不支持
OUTPUT、调用时用变量绑定、客户端注册时序号/类型匹配。少一个环节,值就丢了,而且往往悄无声息。

















