MySQL存储过程参数不支持DEFAULT关键字,默认值需用IFNULL或IF手动实现。所有版本均未实现SQL:2003标准该语法,调用时必须显式传NULL,不可省略参数位置。
MySQL 存储过程不支持 DEFAULT 关键字定义输入参数默认值,任何在 CREATE PROCEDURE 参数列表里写 IN age INT DEFAULT 18 的尝试都会触发 ERROR 1064 (42000)。
MySQL 5.0 至 8.0 所有稳定版本均未实现 SQL:2003 标准中“存储过程参数默认值”语法。你看到的所谓“支持”,基本是以下混淆:
DECLARE v_age INT DEFAULT 18 是局部变量声明,和输入参数无关CALL proc('a', DEFAULT) 是显式传入关键字 DEFAULT,不是省略参数,且该用法本身在 MySQL 中也不被真正支持(会报错或被忽略)DEFAULT(如 gender VARCHAR(10) DEFAULT 'Unknown')和存储过程参数毫无关系这是最简、最安全、最常用的做法:在 BEGIN 后第一行就重设参数值,后续所有逻辑都基于已确定的值运行。
SET age = IFNULL(age, 18); —— 适合单默认值,简洁明了SET name = COALESCE(name, 'Unknown', ''); —— 支持多备选,但第二层几乎用不到IFNULL 只识别 NULL,对空字符串 '' 无效;若业务上 '' 也算“未提供”,得写成 IF age IS NULL OR age = '' THEN SET age = 18; END IF;
IFNULL 第二个参数里写表达式(如 CURDATE()),否则报错当默认逻辑超出简单替换时,IF 是唯一选择:
IF config_value IS NULL THEN SELECT default_age INTO config_value FROM sys_config WHERE key = 'user_default_age'; END IF;
IF age IS NULL THEN SET age = CASE WHEN is_adult THEN 18 ELSE 12 END;
IF username IS NULL THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'username required'; END IF;
这是最容易翻车的地方:MySQL 存储过程严格按位置匹配参数,不存在“跳过中间参数”的语法。
CALL add_user('Alice', NULL); —— 显式传 NULL 触发默认逻辑CALL add_user('Alice'); —— 报错 Incorrect number of arguments
CALL add_user('Alice', DEFAULT); —— DEFAULT 不是合法值,实际执行会失败或被当作字符串字面量真正的难点不在“怎么写默认逻辑”,而在于所有人——包括文档、IDE 提示、甚至部分老 DBA —— 都可能下意识认为 DEFAULT 在参数声明里有效。它就是无效,且永远不会有兼容性补丁。每次写存储过程前,先默念一遍:参数无默认,全靠 IFNULL 或 IF 手动兜底,调用必传 NULL。