SQL Server和MySQL存储过程参数均需以@开头、严格区分IN/OUT方向,不支持动态对象名传参,必须用字符串拼接加安全校验;默认值参数须置末尾,调用时禁用混合传参方式。

SQL Server 中创建带多个参数的存储过程
SQL Server 存储过程支持 IN、OUT、OUTPUT 三种参数模式,默认是 IN。参数名必须以 @ 开头,且在过程内唯一。
常见错误:漏写 @ 前缀(如写成 customerid 而非 @customerid),或把参数名和变量名混用导致作用域冲突。
- 创建时用
CREATE PROCEDURE,参数列表直接写在括号里,例如:CREATE PROCEDURE GetOrdersByDate @start_date DATE, @status NVARCHAR(20) = N'Active' - 带默认值的参数(如
@status)可省略传入,但必须放在参数列表末尾;否则调用时会因位置错位报错Procedure or function 'xxx' expects parameter '@xxx', which was not supplied. - Unicode 字符串必须加前缀
N,比如@status = N'Shipped';否则可能因字符集转换导致匹配失败
MySQL 中声明和调用多参数存储过程
MySQL 使用 IN / OUT / INOUT 明确标注参数方向,不支持默认值语法(5.7 及以前),8.0+ 支持 = DEFAULT,但实践中仍建议显式传参。
容易踩的坑:调用时用 CALL,不是 EXEC;参数顺序必须严格匹配定义顺序,不能跳过中间参数只传第1个和第3个。
- 定义示例:
CREATE PROCEDURE SearchUser(IN p_name VARCHAR(50), IN p_age INT, OUT p_count INT) - 调用前需先声明输出变量:
SET @cnt = 0; CALL SearchUser('Alice', 30, @cnt); SELECT @cnt; - 若误写成
CALL SearchUser('Alice', @cnt, 30),会导致类型不匹配或值被意外覆盖
传参时混合命名与位置方式会直接报错
SQL Server 和 MySQL 都不允许同一调用中既用名字又用位置。比如 EXEC proc @a = 1, 2 或 CALL proc('x', @out)(其中第一个是值、第二个是变量名)都会触发解析失败。
典型报错信息:Incorrect syntax near ','(SQL Server)或 Parameter mismatch: procedure expects 3 parameters, 2 given(MySQL)。
- 推荐统一用命名方式:SQL Server 写
EXEC proc @p1 = 'x', @p2 = 123;MySQL 写CALL proc(p1 => 'x', p2 => 123)(8.0+ 支持,兼容性需确认) - 若坚持位置传参,务必核对
sys.parameters(SQL Server)或SHOW CREATE PROCEDURE xxx(MySQL)里的参数顺序 - 函数不能直接当参数值,
EXEC proc GETDATE()会报错;应先赋值:DECLARE @now DATETIME = GETDATE(); EXEC proc @dt = @now
动态表名或列名无法通过参数直接传递
存储过程参数只能传值,不能传对象名(如表名、列名、数据库名)。试图写 SELECT * FROM @table_name 会报错 Must declare the table variable "@table_name"。
真正需要动态对象名时,必须拼接字符串 + EXEC(SQL Server)或 PREPARE(MySQL),但这引入 SQL 注入风险,且无法复用执行计划。
- 安全做法:白名单校验 +
CASE分支代替动态 SQL,例如:IF @target_table = 'orders' SELECT * FROM orders; ELSE IF @target_table = 'users' SELECT * FROM users; - 不得已用动态 SQL 时,SQL Server 用
QUOTENAME()包裹标识符,MySQL 用反引号:CONCAT('SELECT * FROM `', @table_name, '`') - 注意:MySQL 的
PREPARE不支持参数化表名/列名,只能拼接;而 SQL Server 的sp_executesql同样不接受表名作为参数
实际用的时候,参数数量一超过三个,就很容易漏掉某个 @ 或搞反顺序。最稳妥的办法是调用前先查 sys.parameters 或 SHOW CREATE PROCEDURE 确认签名,别靠记忆。


















