out参数必须通过预先声明的变量接收,不可直接赋值或忽略;pl/sql中需在declare声明兼容类型变量、调用时传变量名(无冒号);jdbc需registeroutparameter在execute前且索引从1开始;c#需正确设置direction为output;sql*plus需variable声明后用:var绑定并print查看。

OUT 参数不是“返回值”,它必须通过变量接收,不能直接赋值或忽略声明 —— 这是调用失败最常见的原因。
PL/SQL 匿名块里怎么传 OUT 参数?
必须先声明兼容类型的变量,再在 BEGIN 中作为实参传入,否则会报 PLS-00363: expression 'xxx' cannot be used as an assignment target。
-
DECLARE部分声明变量,类型要和OUT参数一致(比如VARCHAR2(100)或用%TYPE) - 调用时直接写变量名,不要加冒号(
:)或引号 - 如果存储过程有多个
OUT参数,每个都得配一个变量 -
DBMS_OUTPUT.ENABLE要提前开,否则PUT_LINE不显示
示例:
DECLARE v_name VARCHAR2(50); v_dept VARCHAR2(30); BEGIN get_emp_info(101, v_name, v_dept); -- 注意:这里没冒号,v_name 和 v_dept 是变量名 DBMS_OUTPUT.PUT_LINE(v_name || ', ' || v_dept); END;
JDBC 里 registerOutParameter 必须在 execute 前调用
顺序错、类型错、索引错,三者任一都会导致 SQLException,常见错误是 Invalid column index 或 ORA-06550。
-
CallableStatement的参数索引从 1 开始,不是 0 -
registerOutParameter必须在setXXX之后、execute之前 -
Types.VARCHAR对应VARCHAR2,Types.NUMERIC对应NUMBER,不能混用 - 如果
OUT参数可能为NULL,要用getString(2)而不是getNString(2),后者在旧驱动里容易 NPE
关键代码片段:
String sql = "{call get_employee_name(?, ?)}";
CallableStatement cs = conn.prepareCall(sql);
cs.setInt(1, 101); // IN 参数
cs.registerOutParameter(2, Types.VARCHAR); // OUT 参数,索引 2
cs.execute();
String name = cs.getString(2); // 必须用 same index
C# 的 OracleParameter.Direction = ParameterDirection.Output 不能漏
用 System.Data.OracleClient(已弃用)或 Oracle.ManagedDataAccess 时,Direction 属性不设或设错,会导致参数被当成 IN,最终 Value 为空或抛 ORA-01036。
- 变量名必须和存储过程中定义的参数名**完全一致**(大小写敏感,取决于创建时是否加双引号)
- 不能用
?占位符配合命名参数,Oracle 不支持混合占位;必须统一用命名(如:p_name)或全位置(?) -
Value初始值设为DBNull.Value,尤其当可能传NULL时,否则运行时报Object reference not set -
ExecuteNonQuery()才能触发OUT参数填充,ExecuteReader()不适用
SQL*Plus / SQL Developer 里用 VARIABLE 和 EXEC 的坑
这不是 PL/SQL,而是客户端变量绑定机制,EXEC 后不能直接引用变量,必须用 PRINT 或 SELECT :var FROM DUAL 查看。
-
VARIABLE声明后,变量名前加冒号(:v_name)才表示绑定 -
EXEC proc_name(101, :v_name)中的:v_name必须已声明,否则报SP2-0552: Bind variable "v_name" does not exist -
PRINT v_name不能带冒号,而SELECT :v_name FROM DUAL必须带冒号 -
VARCHAR2变量长度不够会截断,建议声明时留足余量(如VARIABLE v_name VARCHAR2(200))
OUT 参数本质是“双向通道”,但只在执行结束后单向输出;最容易被忽略的是:它要求调用方主动提供容器变量,而不是靠过程自己“吐”出来——所有语言和工具都绕不开这层契约。











