SQL Server支持参数默认值但必须从右向左连续声明;MySQL不支持DEFAULT语法,需用IFNULL或IS NULL手动处理;PostgreSQL仅plpgsql函数支持DEFAULT,且默认值编译时求值。

SQL Server 支持参数默认值,但必须从右向左连续声明
SQL Server 是少数原生支持 DEFAULT 关键字定义输入参数默认值的数据库。但限制很明确:带默认值的参数必须放在参数列表末尾,且不能跳过中间项。
常见错误写法:CREATE PROCEDURE p @a INT = 1, @b INT, @c VARCHAR(10) = 'x' —— 这会直接报错 Incorrect syntax near '=',因为 @b 没默认值却夹在两个有默认值的参数之间。
正确做法是把所有可选参数集中放右侧,并按从右到左顺序设默认值:
CREATE PROCEDURE GetOrders
@page INT = 1,
@size INT = 20,
@status VARCHAR(20) = 'Active'
AS
SELECT * FROM orders
WHERE status = @status
ORDER BY created_at
OFFSET (@page - 1) * @size ROWS
FETCH NEXT @size ROWS ONLY;调用时可省略右侧参数:EXEC GetOrders @page = 3,@size 和 @status 自动取默认值;若想跳过 @size 只指定 @status,必须用命名参数:EXEC GetOrders @page = 1, @status = 'Pending'。
MySQL 不支持参数 DEFAULT 语法,必须手动处理 NULL
MySQL 5.0–8.0 所有版本都不支持在 CREATE PROCEDURE 的参数声明中使用 DEFAULT。写 IN age INT DEFAULT 18 会触发 ERROR 1064 (42000)。
真正能用的只有两种方式:
-
SET age = IFNULL(age, 18);—— 最简方案,适合静态默认值,但注意IFNULL只识别NULL,对空字符串''无效 -
IF age IS NULL THEN SET age = (SELECT default_age FROM sys_config WHERE key = 'user_default_age');—— 适用于需查表、调函数或带分支逻辑的场景
关键约束:调用时不能省略参数位置。哪怕你写了 IFNULL 处理逻辑,也必须显式传 NULL:CALL add_user('Alice', NULL);CALL add_user('Alice') 会报 Incorrect number of arguments。
PostgreSQL 函数可用 DEFAULT,但仅限 LANGUAGE plpgsql
PostgreSQL 在 CREATE FUNCTION 中支持 DEFAULT 关键字,语法干净:
CREATE OR REPLACE FUNCTION get_users(
role TEXT DEFAULT 'user',
active BOOLEAN DEFAULT true
) RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
RETURN QUERY SELECT u.id, u.name FROM users u
WHERE u.role = role AND u.active = active;
END;
$$ LANGUAGE plpgsql;调用时可省略右侧参数:SELECT * FROM get_users(); 或 SELECT * FROM get_users('admin');。
注意点:
- 该语法只适用于
LANGUAGE plpgsql函数,不适用于sql类型函数 - 仍按位置匹配,不支持跳过中间参数(如
get_users(DEFAULT, false)是非法的) - 默认值表达式在函数编译时求值一次,不是每次调用都重算(除非写成
DEFAULT now()这类运行时函数)
默认值逻辑里最容易被忽略的三个细节
无论用哪种数据库,以下三点常被跳过,导致线上行为异常:
-
IFNULL和COALESCE对空字符串''、数字0、布尔false完全无感——它们只响应NULL。业务上若认为''等价于“未提供”,得写成IF p_name IS NULL OR p_name = '' THEN SET p_name = 'Unknown'; - 显式传
NULL会触发默认逻辑,但有时NULL是合法业务值(比如“年龄未知”)。此时必须加额外标记字段,或改用特殊哨兵值(如-1)区分 - SQL Server 中
DEFAULT参数若依赖函数(如GETDATE()),不能直接写在参数声明里:@ts DATETIME = GETDATE()是语法错误;必须在过程体内用SET @ts = ISNULL(@ts, GETDATE())

















