mysql存储过程参数必须显式声明in/out/inout模式,out/inout参数调用时须用@用户变量接收,过程内须用select...into或set显式赋值,否则返回null;delimiter需成对设置以避免语法错误。

必须显式声明参数模式(IN/OUT/INOUT),且调用时输出参数必须用用户变量(@var)接收,否则值无法传出。
参数声明必须带模式关键字,不能省略
MySQL 8.0 不允许省略 IN、OUT 或 INOUT。哪怕你只想要一个输入参数,也得写 IN param_name type,不能只写 param_name type —— 否则会报语法错误 ERROR 1064。
-
IN参数用于传入值,过程内可读不可赋值(赋值无效) -
OUT参数初始为NULL,必须在过程体内用SELECT ... INTO或SET显式赋值,否则调用后仍是NULL -
INOUT参数既可读又可写,调用前需先设初值(如SET @x = 10),过程内可修改,返回时带新值
调用时输出参数必须用用户变量,不能用字面量或局部变量
调用带 OUT 或 INOUT 的存储过程时,对应实参只能是形如 @var 的会话级用户变量。直接写数字、字符串或未声明的变量名都会失败。
- ✅ 正确:
CALL myproc(123, @result); SELECT @result; - ❌ 错误:
CALL myproc(123, 'dummy');(字符串字面量不能接收输出) - ❌ 错误:
CALL myproc(123, result);(result是未定义标识符,不是变量) - ⚠️ 注意:
@变量作用域是当前会话,断开连接后丢失;不同连接间不共享
SELECT ... INTO 是给 OUT/INOUT 赋值最常用方式
想把查询结果赋给输出参数,必须用 SELECT col INTO out_param FROM ...。不能用 = 直接赋查询结果(MySQL 不支持表达式赋值),也不能漏掉 INTO。
- ✅ 正确:
SELECT COUNT(*) INTO total FROM orders WHERE user_id = uid; - ❌ 错误:
total = SELECT COUNT(*) FROM orders WHERE user_id = uid;(语法错误) - ❌ 错误:
SELECT COUNT(*) FROM orders WHERE user_id = uid;(没INTO,值不会进变量) - ? 提示:若查询可能无结果(如
WHERE不匹配),INTO后变量仍为NULL,建议加IF NOT EXISTS或默认值处理
DELIMITER 必须成对设置,且不能和过程体内的分号冲突
MySQL 默认以分号 ; 为语句结束符,但存储过程体内部每条 SQL 都要加分号。所以必须先用 DELIMITER // 换个结束符,等整个 CREATE PROCEDURE 语句写完,再用 DELIMITER ; 恢复。
- ✅ 正确顺序:
DELIMITER //→CREATE PROCEDURE ... BEGIN ... END //→DELIMITER ; - ❌ 常见错:
DELIMITER //写了,但结尾忘了DELIMITER ;,导致后续所有命令都被当做一个长语句解析 - ? 小技巧:可以用任意符号组合做 delimiter(如
$$、##),只要前后一致且不与过程内容冲突即可
最容易被忽略的是:输出参数即使在过程里被 SET 或 SELECT ... INTO 赋了值,如果调用时没用 @ 用户变量接收,或者调用后没执行 SELECT @var 查看,就等于白干——值根本没出来,还查不到任何报错。











