Oracle存储过程仅IN参数支持默认值,用DEFAULT或:=指定,每次调用动态计算;OUT和IN OUT参数禁止设置,默认值不适用于显式传入的NULL。

PL/SQL 中声明带默认值的 IN 参数语法正确写法
Oracle 的 PL/SQL 支持在存储过程参数列表中直接为 IN 参数指定默认值,用 := 或 =(二者等价)赋初始值,且无需额外判断逻辑。
关键点是:默认值只对未传参或传 NULL 的调用生效;若显式传了 NULL,该 NULL 会覆盖默认值——这是和 SQL Server 行为的重要区别。
-
IN参数默认可省略IN关键字,但加上更清晰 - 默认值必须是编译期可确定的表达式,比如字面量、函数调用(如
SYSDATE)、常量,不能是变量或列名 - 支持混合声明:部分参数带默认值,部分不带;但建议把带默认值的参数放在靠后位置,便于调用时省略
- 示例:
CREATE OR REPLACE PROCEDURE log_message ( p_level IN VARCHAR2 := 'INFO', p_msg IN VARCHAR2, p_user IN VARCHAR2 := USER ) AS BEGIN INSERT INTO app_log(level, msg, created_by) VALUES (p_level, p_msg, p_user); END;
调用时传 NULL 会跳过默认值,这点必须注意
PL/SQL 不区分“未传参”和“显式传 NULL”——只要调用时写了 NULL,哪怕该参数有默认值,也会被当作有效输入,NULL 直接进入过程体。
这意味着:如果你希望「传 NULL」也触发默认行为,必须在过程体内手动检查:
- 错误写法(以为
NULL会自动 fallback):log_message(NULL, 'test')→p_level得到NULL,不是'INFO' - 正确应对方式(显式兜底):
IF p_level IS NULL THEN p_level := 'INFO'; END IF;
- 也可用
NVL或COALESCE,但注意它们在NULL场景下语义一致,不改变参数原始值
OUT 和 IN OUT 参数不能直接设默认值
PL/SQL 明确禁止为 OUT 或 IN OUT 类型的参数指定默认值,语法报错:PLS-00103: Encountered the symbol "="。
原因在于:这类参数的值由过程内部生成或修改,外部无法提供“默认输入”。如果需要类似效果,只能在过程体内初始化:
- 在
DECLARE/AS块后、BEGIN前给对应变量赋初值 - 或在
BEGIN开头立即:=赋值 - 例如:
CREATE OR REPLACE PROCEDURE get_emp_name ( p_empno IN NUMBER, p_ename OUT VARCHAR2 ) AS BEGIN p_ename := 'UNKNOWN'; -- 手动初始化,替代“默认值” SELECT ename INTO p_ename FROM emp WHERE empno = p_empno; EXCEPTION WHEN NO_DATA_FOUND THEN NULL; END;
与 SQL Server / MySQL 的关键差异提醒
别套用其他数据库的习惯。PL/SQL 的默认参数机制最接近 SQL Server(都支持语法级默认值),但不强制“从右向左连续”——你可以中间参数不设默认值,右侧再设,不会报错;而 SQL Server 会拒编译。
MySQL 完全不支持该语法,必须靠过程体内 IF p_x IS NULL THEN SET p_x = ... 模拟;PostgreSQL 存储过程(PROCEDURE)也不支持,默认值需在调用端处理或用函数(FUNCTION)替代。
真正容易被忽略的是:PL/SQL 默认值不解决 NULL 语义歧义问题,业务上是否允许 NULL 作为合法输入,必须提前约定清楚,否则调用方一个 NULL 就让默认逻辑失效。

















