必须显式声明OUTPUT关键字,定义时写成@param INT OUTPUT,调用时用EXEC proc @var OUTPUT;常量、表达式不可作为OUTPUT目标,仅支持可写变量;类型须严格匹配,适合标量值传递。

SQL Server 中必须显式声明 OUTPUT 关键字
被调用存储过程的参数定义里,OUTPUT 修饰符不能省略——哪怕你在过程内部给它赋了值,没写 OUTPUT 就只是个普通输入参数,调用方永远收不到。常见错误是定义时漏掉,或者误以为“只要 SET 了就能传出来”。
- 定义必须写成:
@status_code INT OUTPUT,不是@status_code INT - 调用时变量前也必须加
OUTPUT:EXEC dbo.usp_check @result OUTPUT - 不加关键字的写法(如
EXEC dbo.usp_check @result)等价于只传入值,不会回写
调用端必须用变量接收,不能用常量或表达式
OUTPUT 参数本质是内存地址传递,要求目标位置可写。传入字面量、计算结果或字段名都会直接报错。
- ✅ 正确:
DECLARE @ret INT; EXEC dbo.usp_get @ret OUTPUT - ❌ 错误:
EXEC dbo.usp_get 123 OUTPUT(常量不可写) - ❌ 错误:
EXEC dbo.usp_get (@a + @b) OUTPUT(表达式无确定内存地址) - 如果参数同时作输入输出,调用前需先初始化:
SET @cnt = 0; EXEC dbo.usp_inc @cnt OUTPUT
多个 OUTPUT 参数要严格匹配类型和顺序
SQL Server 默认按位置绑定参数,类型错配会立即报错;命名绑定虽可用,但容易掩盖隐式转换风险。
- 推荐显式按名调用:
EXEC dbo.usp_multi @id OUTPUT, @name OUTPUT, @ts OUTPUT - 避免仅靠位置传参,尤其当参数列表含可选参数时
- 类型必须一致:定义为
@val DECIMAL(10,2) OUTPUT,就不能传@v INT OUTPUT,即使数值能转,也可能截断或精度丢失 - NULL 可正常传出,但若过程内没赋值,接收变量保持原值(不是自动变 NULL)
OUTPUT 不适合传大量数据或结构化内容
它只适合标量值——ID、计数、状态码、时间戳。试图把 JSON 或 XML 塞进 @json_out NVARCHAR(MAX) OUTPUT 看似可行,实则埋坑。
- 性能上:大字符串触发额外内存拷贝和网络传输开销
- 可维护性差:调用方还得手动解析,不如直接返回结果集清晰
- 调试困难:SSMS 执行窗口不显示 OUTPUT 值,除非你显式
SELECT @p1, @p2 - 真正需要多行或多字段数据时,该用
INSERT INTO #tmp EXEC ...或表变量捕获结果集
OUTPUT,二是调用时变量前忘加 OUTPUT 关键字——这两个地方一错,整个输出就静默失效,还查不出原因。

















