SQL Server中EXEC调用存储过程必须显式使用OUTPUT关键字传递输出参数,被调过程定义和调用语句均需严格匹配类型与OUTPUT声明;RETURN值仅支持整数且须用EXEC @ret=proc捕获;结果集必须通过结构完全一致的临时表承接,跨库调用需三段式名称并确保权限与嵌套深度合规。

SQL Server 中用 EXEC 调用必须显式加 OUTPUT 才能传回参数
很多人以为声明变量后直接 EXEC sp_proc @var 就能拿到输出值,结果 @var 始终是 NULL。真正生效的写法必须两边都带 OUTPUT:
- 调用方:声明变量 +
EXEC sp_proc @param OUTPUT - 被调过程定义里也得是
@param INT OUTPUT,类型和方向严格一致 - 漏掉任意一个
OUTPUT,参数就失效,过程不报错但值没传出来
想拿 RETURN 整数状态码?必须用 EXEC @ret = proc 捕获
RETURN 只能是整数,且不能像函数那样嵌入表达式。常见错误包括:SELECT * FROM (EXEC proc) 或 @ret = EXEC proc——全会语法报错。
- 正确写法:
DECLARE @result INT; EXEC @result = usp_CheckUser @id = 123; - 被调过程里必须有明确
RETURN 1、RETURN -1这类语句;没写RETURN默认返回 0 - 该语法仅限 SQL Server;MySQL / PostgreSQL 不支持
EXEC @var =形式
要取 SELECT 结果集?只能用临时表承接,别碰表变量
EXEC 本身不返回结果集给调用方,强行 SELECT * FROM (EXEC sp) 会语法报错。唯一可靠方式是用临时表结构匹配承接:
- 先建
#tmp或##tmp,列名、数量、类型、顺序必须和被调过程的SELECT输出一模一样 - 写成
INSERT INTO #tmp EXEC sp_name @param,不能用表变量(DECLARE @t TABLE())配合INSERT INTO @t EXEC,SQL Server 会拒绝 - 跨库调用时,临时表结构还得匹配远程过程的实际输出,否则插入失败或数据截断
跨数据库调用必须用三段式名称,权限和嵌套深度常静默失败
写 EXEC sp_name 看似省事,实际极容易调错对象——尤其当两个库都有同名过程,或当前用户默认 schema 不是 dbo 时:
- 正确写法是
EXEC [OtherDB].[dbo].[sp_name]或简写为EXEC OtherDB..sp_name - 调用方账号必须有目标过程的
EXECUTE权限,跨库时还要确认是否授权到具体 schema - 嵌套调用深度不能超过 32 层,递归或环形依赖(A→B→C→A)会直接触发
Msg 8152错误;调试时可用SELECT @@NESTLEVEL实时查看层级
最易被忽略的是输出参数的 OUTPUT 关键字和临时表列定义——这两处出错,过程跑完没报错,数据却为空或类型错位,查起来特别耗时间。











