输入参数必须显式声明、带@前缀,类型严格匹配,禁止混用位置与命名传参方式,否则直接报错;默认值参数须置末尾,函数不可直传需先赋值变量,Unicode字符串须加N前缀。

输入参数必须显式声明、带 @ 前缀,且不能跳过或混用传参方式,否则直接报错。
参数声明必须以 @ 开头,且类型要匹配
SQL Server 和 MySQL 都要求输入参数名以 @ 开头(MySQL 实际不强制,但 SQL Server 严格要求),否则执行时会提示 Must declare the scalar variable "@xxx"。参数类型必须与调用值一致:比如声明为 @status NVARCHAR(20),传入就得是 N'Shipped'(加 N 前缀),否则可能因字符集隐式转换导致 WHERE 匹配失败。
-
@productid INT→ 只能传整数,'5'(字符串)会隐式转换,但'abc'直接报错 -
@name NVARCHAR(50)→ 推荐用N'张三',避免乱码;用'张三'在某些排序规则下可能截断或失真 - MySQL 中虽不强制
@前缀(定义时用p_name VARCHAR(50)),但调用时仍需按顺序或命名传递,且变量名不带@
调用时不能混合位置和命名方式
这是最常踩的坑:同一句 EXEC 或 CALL 中,要么全用位置(EXEC proc 1, N'Active'),要么全用命名(EXEC proc @id = 1, @status = N'Active')。一旦混用,SQL Server 报 Incorrect syntax near ',',MySQL 报 Parameter mismatch。
- 位置传参必须严格按
CREATE PROCEDURE中的顺序,漏掉中间参数就会错位 - 命名传参可打乱顺序,但所有参数都得写成
@param = value格式,且第一个用了命名,后面全得跟上 - MySQL 8.0+ 支持
p_name => 'x'形式,但低版本不兼容,生产环境建议统一用位置或显式变量赋值
函数不能直接当参数值,得先存到变量里
EXEC proc GETDATE() 这种写法在 SQL Server 和 MySQL 中都会失败。系统不允许把函数调用结果直接当参数传入,必须先赋值给变量再传。
- 正确做法:
DECLARE @now DATETIME = GETDATE(); EXEC proc @dt = @now; - MySQL 类似:
SET @ts = NOW(); CALL proc(@ts); - 即使看起来“只是个时间”,
GETDATE()、NOW()、LEN()等都不被接受为直接参数值 - 这个限制也适用于子查询,
EXEC proc (SELECT TOP 1 id FROM t)同样非法
默认值参数必须放在参数列表末尾
如果定义了带默认值的参数(如 @limit INT = 10),它必须排在所有无默认值参数之后。否则调用时省略该参数,会导致前面非默认参数被“顶替”,触发 expects parameter '@xxx', which was not supplied 错误。
- 合法:
CREATE PROC p @a INT, @b VARCHAR(10), @c INT = 5 - 非法:
CREATE PROC p @a INT, @b INT = 5, @c VARCHAR(10)—— 即使调用时传了@a和@c,@b的默认值也不会生效 - MySQL 5.7 不支持默认值语法,8.0+ 虽支持
= DEFAULT,但实践中仍建议显式传参,避免版本差异引发问题
真正容易被忽略的是参数作用域和 Unicode 处理:同一个存储过程中,@var 不能既当输入参数又当局部变量重声明;而 N'string' 这种前缀不是可选优化,是防止 NVARCHAR 字段匹配失效的关键操作。

















