Oracle 存储过程仅 IN 参数支持默认值,OUT 和 IN OUT 参数禁止设置,默认值在每次调用时动态计算,DEFAULT 与 := 等价但推荐统一用 DEFAULT,调用时可省略尾部默认参数或使用命名方式。
oracle 存储过程的 in 参数可以设默认值,out 和 in out 不行 —— 这是硬限制,不是语法疏忽,强行加会报 pls-00363 或编译失败。
DEFAULT 只对 IN 参数生效
Oracle 明确禁止为 OUT 和 IN OUT 参数指定默认值。哪怕只写 DEFAULT NULL 或 := NULL,编译时就会拒绝:
-
CREATE OR REPLACE PROCEDURE p_test(p_out OUT VARCHAR2 DEFAULT 'x')→ 直接报错PLS-00363: expression 'P_OUT' cannot be used as an assignment target -
IN是唯一支持默认值的参数模式;不写模式时默认就是IN,所以p_name VARCHAR2 DEFAULT 'N/A'是合法的 - 默认值表达式每次调用都重新计算,比如
SYSDATE、USER、100 * 2都没问题,不是“创建时固化”的
DEFAULT 和 := 两种写法等价,但风格要统一
你可以用 DEFAULT 关键字,也可以用赋值运算符 :=,效果完全一样:
CREATE OR REPLACE PROCEDURE hire_emp( p_empno NUMBER, p_ename VARCHAR2, p_hiredate DATE DEFAULT SYSDATE ) IS ...
等价于:
CREATE OR REPLACE PROCEDURE hire_emp( p_empno NUMBER, p_ename VARCHAR2, p_hiredate DATE := SYSDATE ) IS ...
- 混用(比如一个参数用
DEFAULT,另一个用:=)虽不报错,但可读性差,团队协作中容易引发歧义 - 推荐统一用
DEFAULT,更贴近 SQL 标准,也和CREATE FUNCTION的习惯一致 - 注意:
:=不能用于OUT参数声明位置,否则语法错误,不是“不生效”,而是根本解析不过
调用时省略默认参数,顺序和命名必须匹配
设了默认值后,调用可以少传参数,但必须满足两个条件之一:
- 按顺序省略尾部参数:比如
hire_emp(7575, 'Clark')合法,因为p_hiredate在最后且有默认值 - 用命名方式跳过中间参数:
hire_emp(p_empno => 7575, p_ename => 'Clark')也合法,顺序无关 - 但
hire_emp(7575, DEFAULT, '15-FEB-2010')是非法写法 —— Oracle 不支持DEFAULT作为实参关键字 - 如果参数在中间有默认值(如第2个参数),又想省略它,就必须用命名方式,否则位置错位会导致类型/逻辑错误
默认值不是“空值兜底”,而是显式参与逻辑
默认值一旦被采用,就和手动传入的值一样参与整个 PL/SQL 执行流程 —— 它不是“NULL 替代品”,也不会触发 NVL 类逻辑:
- 比如
p_salary NUMBER DEFAULT 1000,调用时没传,那p_salary就是数值1000,不是NULL,后续做IS NULL判断会为FALSE - 如果业务上需要区分“用户没传”和“用户传了 1000”,默认值机制做不到,得改用
IN参数 + 单独标志位,或改用FUNCTION返回是否设置 - 事务内默认值不影响回滚行为 —— 它只是参数初始化值,不改变存储过程本身的事务边界
最容易被忽略的是:默认值只解决“调用简洁性”,不解决“语义模糊性”。当多个参数都有默认值,又混合位置调用和命名调用时,极易因顺序理解偏差导致数据写错。真要兼顾灵活性和健壮性,建议默认值只用于明确无歧义的尾部参数,且文档里写清每个默认值的实际含义和业务约束。











