SQL Server用EXEC加OUTPUT关键字传参,MySQL用CALL配OUT参数,Oracle在PL/SQL块中直接写过程名;三者语法互不兼容,获取结果须分别用临时表、OUT参数或游标承接。

SQL Server、MySQL、Oracle 的存储过程调用语法完全不同,不能混用;想拿到结果(值或数据行),必须用对应机制承接,EXEC 或 CALL 本身不返回可赋值的结果。
SQL Server 中 EXEC 调用必须显式加 OUTPUT 才能传回参数
很多人写 EXEC sp_proc @var 就以为 @var 能拿到输出值,结果始终是 NULL。根本原因是:输出参数必须双向声明 —— 调用方写 EXEC sp_proc @param OUTPUT,被调过程定义里也得是 @param INT OUTPUT,类型和方向缺一不可。
- 漏掉任意一个
OUTPUT关键字,SQL Server 不报错,但参数不会传递 - 返回值(
RETURN)只能是整数,且必须用EXEC @ret = sp_proc捕获,不能用于字符串或结果集 - 想让被调过程返回多列数据?别指望
RETURN或输出参数,得用临时表承接
SQL Server 获取结果集必须用临时表,不能用表变量
EXEC 本身不返回结果集给调用方,SELECT * FROM (EXEC sp) 是语法错误。唯一可靠方式是提前建好结构匹配的临时表,再用 INSERT INTO #tmp EXEC sp_name 插入。
- 临时表列名、数量、类型、顺序必须和被调过程的
SELECT输出完全一致,否则插入失败或数据截断 -
DECLARE @t TABLE(...)配合INSERT ... EXEC会被 SQL Server 显式拒绝 - 跨库调用时,临时表结构还得匹配远程过程的实际输出,不能只看本地同名过程
MySQL 用 CALL + OUT 参数,没有 RETURN 值概念
MySQL 存储过程不支持 RETURN 语句返回状态码,所有“返回”都靠 OUT 或 INOUT 参数。调用时直接传变量名,不用写 OUT 关键字,但被调过程定义中必须明确声明。
- 例如
CALL check_user_active(uid, status_code),前提是被调过程定义为OUT status_code INT - 字符串类输出要注意长度限制,如
OUT msg VARCHAR(100),超长会被静默截断 - 结果集无法通过参数返回,需在主过程中用游标遍历,或改用视图/临时表中转
跨库调用必须用三段式名称,权限和嵌套深度常被忽略
写 EXEC sp_name 看似省事,实际极容易调错对象——尤其当两个库都有同名过程,或当前用户默认 schema 不是 dbo 时。
- 正确写法是
EXEC [OtherDB].[dbo].[sp_name]或简写为EXEC OtherDB..sp_name - 调用方账号必须有目标过程的
EXECUTE权限,跨库时还要确认是否授权到具体 schema - 嵌套调用深度不能超过 32 层,递归或环形依赖会触发
Msg 8152错误;调试时可用SELECT @@NESTLEVEL实时查看层级
最容易被忽略的是输出参数的 OUTPUT 关键字和临时表列定义——这两处出错,过程跑完没报错,数据却为空或类型错位,查起来特别耗时间。

















