SQL Server中声明输出参数必须显式使用OUTPUT关键字,调用时EXEC也需带OUTPUT,过程体内须显式赋值,且建议开头加SET NOCOUNT ON。

CREATE PROCEDURE 声明输出参数必须带 OUTPUT 关键字
SQL Server 不接受省略 OUTPUT 的写法,哪怕你只打算在过程里赋值、不打算返回——只要想让调用方拿到值,声明时就必须加 OUTPUT。漏掉这个关键字,参数就是纯输入参数,调用后变量值不会变。
常见错误:@TotalCount int → 实际需要写成 @TotalCount int OUTPUT;@Result varchar(50) = 'default' 也不能代替 OUTPUT,默认值和输出能力是两回事。
输入参数可以不加 OUTPUT,但所有输出参数必须显式标注,且只能出现在参数列表末尾(SQL Server 允许混合,但建议把 OUTPUT 参数统一放在后面,避免混淆)。
过程体内必须对 OUTPUT 参数赋值,否则返回 NULL
声明了 @Status int OUTPUT,不代表它自动有值。SQL Server 不会初始化输出参数,也不做隐式赋值。如果没在 BEGIN...END 里给它设值,调用后得到的就是 NULL,哪怕你声明时写了默认值。
赋值方式不限,但必须是显式操作:
SELECT @Status = COUNT(*) FROM users WHERE active = 1SET @Status = CASE WHEN @InputID > 0 THEN 1 ELSE -1 ENDIF EXISTS (...) SET @Status = 1 ELSE SET @Status = 0
注意:不能只靠 INSERT/UPDATE/DELETE 的行计数间接影响输出参数——这些语句不会自动填入 @ 变量。
调用时 EXEC 必须带 OUTPUT 关键字,且位置紧贴变量名
这是最容易翻车的点。声明用了 OUTPUT,过程体也赋了值,但调用时漏掉 OUTPUT,结果还是原变量值(比如初始为 0 或 NULL)。
正确写法只有两种:
- 位置传参:
EXEC dbo.GetUserCount @DeptID, @Result OUTPUT(顺序必须和声明一致) - 命名传参:
EXEC dbo.GetUserCount @DeptID = 101, @Result = @out OUTPUT(OUTPUT必须紧跟在@Result = @out后面,不能写成@Result OUTPUT = @out)
混用直接报错:EXEC dbo.GetUserCount 101, @Result = @out OUTPUT → 前面位置、后面命名,SQL Server 拒绝执行。
SET NOCOUNT ON 是输出参数稳定的必要前提
不加 SET NOCOUNT ON 不会导致输出参数失效,但会让客户端收到额外的“X 行受影响”消息。在程序调用(如 C# 的 SqlCommand)或嵌套存储过程中,这些干扰消息可能被误判为结果集,导致读取逻辑崩溃或超时。
所以每个带输出参数的存储过程开头都该加:
SET NOCOUNT ON;
结尾可选 SET NOCOUNT OFF,但通常没必要——作用域只在当前批处理内。另外,OUTPUT 参数和 RETURN 值互不影响,别指望用 RETURN 替代输出参数传复杂数据(它只能返回 int)。











