PreparedStatement 不支持输出参数,仅用于带IN参数的SQL语句;调用含OUT/INOUT参数的存储过程必须使用CallableStatement,并需先registerOutParameter再execute后getXXX获取值。

Java 的 PreparedStatement 本身不支持设置“输出参数”(out parameter),因为它专为执行预编译的 SQL 语句(如 INSERT、UPDATE、SELECT)设计,而输出参数是存储过程(Stored Procedure)特有的概念。
输出参数只适用于 CallableStatement
如果你需要调用带 OUT 或 INOUT 参数的数据库存储过程,必须使用 CallableStatement,它是 PreparedStatement 的子接口,专门用于执行存储过程调用。
-
PreparedStatement:用于参数化 SQL 查询/更新,只有IN参数(即输入参数) -
CallableStatement:用于调用存储过程,支持IN、OUT、INOUT参数
如何正确注册和获取输出参数
以 MySQL 或 Oracle 为例,调用含输出参数的存储过程时,需按以下步骤操作:
- 使用
Connection.prepareCall("{call proc_name(?, ?)}")创建CallableStatement - 对每个
OUT或INOUT参数,调用registerOutParameter(paramIndex, sqlType)注册其 JDBC 类型(如Types.VARCHAR、Types.INTEGER) - 设置
IN参数(如有),调用execute() - 调用
getXXX(paramIndex)(如getString(2))获取输出值
示例(Oracle 存储过程 get_user_name(id IN NUMBER, name OUT VARCHAR2)):
立即学习“Java免费学习笔记(深入)”;
String sql = "{call get_user_name(?, ?)}";
try (CallableStatement cs = conn.prepareCall(sql)) {
cs.setInt(1, 1001); // IN 参数
cs.registerOutParameter(2, Types.VARCHAR); // 注册第2个参数为 OUT
cs.execute();
String userName = cs.getString(2); // 获取输出值
}
常见错误提醒
容易混淆或出错的地方:
- 误用
PreparedStatement调用存储过程 → 报SQLSyntaxErrorException或驱动不支持 - 忘记调用
registerOutParameter()就直接getXXX()→ 抛SQLException(“parameter not registered as output”) - 参数索引从 1 开始,不是 0;且注册顺序、获取顺序必须与 SQL 中 ? 出现顺序一致
- 不同数据库对存储过程语法支持略有差异(如 MySQL 用
CALL p(?,?),Oracle 常用{call p(?,?)}或{? = call p(?)})
替代方案:不用存储过程也能“返回值”
如果只是想获取插入/更新后的生成值(如自增 ID),多数数据库支持标准方式,无需存储过程:
- MySQL:用
Statement.RETURN_GENERATED_KEYS+getGeneratedKeys() - PostgreSQL / SQL Server:在
executeUpdate()后直接取getGeneratedKeys() - JDBC 4.0+ 支持
prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)
这类场景仍用 PreparedStatement,但本质是获取“生成键”,不是传统意义的存储过程输出参数。


















