create procedure 是创建带输入输出参数存储过程的唯一标准方式,output 关键字强制用于声明输出参数;输入参数须以@开头并指定明确类型和默认值(仅限常量或null);输出参数需在声明、过程体内赋值及调用时均显式使用output;传参须统一用位置或命名方式,混用将报错;set nocount on 可避免行计数干扰输出参数稳定性。

CREATE PROCEDURE 是创建带输入输出参数的存储过程的唯一标准方式,OUTPUT 关键字是声明输出参数的强制语法 —— 没有替代写法,也不能省略。
输入参数怎么声明才安全可靠
输入参数必须以 @ 开头,后接合法标识符和明确数据类型;默认值要用 = 赋值,且只能是常量或 NULL(不能是函数、表达式或变量):
-
@CustomerID int:必填输入参数,调用时必须提供值 -
@StartDate datetime = NULL:可选参数,不传时自动为NULL -
@Status char(10) = 'Active':支持字符串默认值,但注意单引号必须存在 - 错误写法:
@Now datetime = GETDATE()→ 会报错,函数不能直接作默认值
OUTPUT 参数必须显式声明+显式赋值
仅在 CREATE PROCEDURE 的参数列表里加 OUTPUT 不够,调用方也得配合;过程内部必须对 @ 开头的输出参数做赋值操作,否则返回 NULL:
- 声明时写成:
@TotalAmount decimal(10,2) OUTPUT - 过程体内必须有类似:
SELECT @TotalAmount = SUM(...) FROM ...或SET @TotalAmount = 123.45 - 调用时也要加
OUTPUT:EXEC dbo.CalculateOrderTotal @OrderID = 1001, @TotalAmount = @out OUTPUT - 漏掉调用端的
OUTPUT关键字,变量不会被修改,值仍是初始状态
参数传递顺序和命名混用的坑
SQL Server 允许两种传参方式,但规则严格,混用容易出错:
- 纯位置传参:
EXEC usp_GetSale @ProductID, @Year, @Result OUTPUT→ 必须严格按CREATE PROCEDURE中声明顺序 - 命名传参:
EXEC usp_GetSale @Year = 2024, @ProductID = 101, @Result = @r OUTPUT→ 可打乱顺序,但一旦用了@name = value,后面所有参数都必须命名 - 错误组合:
EXEC usp_GetSale 101, @Year = 2024, @Result = @r OUTPUT→ 前面位置传、后面命名传,SQL Server 直接报错 - 命名传参时,
OUTPUT关键字必须紧贴变量名后,不能写成@Result OUTPUT = @r
SET NOCOUNT ON 是输出参数稳定的前提
不加 SET NOCOUNT ON 不影响 OUTPUT 参数本身,但会让客户端收到多条“X 行受影响”消息,干扰结果集解析,尤其在嵌套调用或程序对接时容易误判返回状态:
- 每个存储过程开头建议固定加上:
SET NOCOUNT ON; - 它不影响
RETURN值或OUTPUT参数,只抑制行计数消息 - 如果过程内有多个
INSERT/UPDATE/DELETE,不加这个会导致网络往返增多,甚至触发某些 ORM 的异常解析逻辑
DECLARE @r int),且调用语句中 OUTPUT 关键字的位置和拼写容错率极低 —— 少一个字母或放错位置,就变成普通输入参数,值根本不会回传。











