SQL Server中OUTPUT参数必须显式声明并调用时加OUTPUT关键字,否则调用端无法获取值;仅支持可写标量类型,需用变量接收且类型严格匹配,不可用常量或表达式,适合传少量标量值。

SQL Server 中 OUTPUT 参数必须显式声明为 OUTPUT 类型
不加 OUTPUT 关键字修饰的参数,哪怕你在存储过程里赋了值,调用端也拿不到。这是最常见的“明明赋值了却为空”的原因。
- 定义时必须写
@param_name datatype OUTPUT,缺OUTPUT修饰符就只是普通输入参数 - 调用时也必须在变量前加
OUTPUT,例如EXEC @ret = dbo.usp_test @p1 OUTPUT, @p2 OUTPUT - 输出参数不能是只读类型(如
table、cursor),也不支持xml类型直接作为 OUTPUT(需转为nvarchar(max)等)
调用时必须用变量接收,不能用常量或表达式
SQL Server 不允许把字面量或计算表达式传给 OUTPUT 参数——它需要一个可写的内存地址来存返回值。
- ✅ 正确:
DECLARE @out_id INT; EXEC dbo.usp_get @out_id OUTPUT; - ❌ 错误:
EXEC dbo.usp_get 123 OUTPUT;(常量不可写) - ❌ 错误:
EXEC dbo.usp_get (@a + @b) OUTPUT;(表达式无地址) - 注意:如果参数同时是输入+输出,仍需先赋初值再传入,比如
SET @cnt = 0; EXEC dbo.usp_inc @cnt OUTPUT;
多个 OUTPUT 参数可以混用,但顺序和类型必须严格匹配
存储过程定义的参数顺序决定了调用时位置绑定的逻辑,命名绑定虽可用但容易掩盖类型错配问题。
- 推荐显式按名调用:
EXEC dbo.usp_multi @id OUTPUT, @name OUTPUT, @ts OUTPUT - 避免仅靠位置传参,尤其当参数列表较长或中间有可选参数时
- 类型不一致会报错,比如过程定义
@val DECIMAL(10,2) OUTPUT,而你传@v INT OUTPUT,即使能隐式转换,也可能截断或报精度错误 - NULL 值可以正常传出,无需额外处理;但如果过程里没赋值,接收变量保持原值(不是自动变 NULL)
OUTPUT 参数无法替代结果集,大数据量别硬塞
OUTPUT 只适合传少量标量值(ID、计数、状态码、时间戳等)。想返回多行数据,该用 SELECT 就用 SELECT,别试图把 JSON 字符串拼进 @json_out NVARCHAR(MAX) OUTPUT 里传出来。
- 性能上:OUTPUT 是内存拷贝,快;但若你塞几 MB 的字符串,反而引发不必要的内存压力和网络传输开销
- 可维护性差:调用方还得手动
JSON_PARSE或XML.NODES(),远不如直接查视图或临时表清晰 - 调试困难:SSMS 执行窗口看不到 OUTPUT 值,除非你
SELECT @p1, @p2显式输出,否则容易误判过程是否执行成功
IF @ret IS NULL SET @ret = -1;,避免调用方拿到未定义值。

















