You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

执行PreparedStatement的IN子句时触发无效数字异常(ORA-01722)

解决ORA-01722无效数字异常

问题原因

你把多个ID拼接成单个字符串传入IN子句的占位符,Oracle会将这个字符串视为单个整体值,而非多个独立数字。当数据库尝试把该字符串转换为数字类型匹配empidList字段时,就会抛出无效数字异常。

解决方案

方案一:动态生成参数占位符(推荐)

生成与ID数量对应的?占位符,让PreparedStatement逐个设置参数,既符合参数化查询规范,又能避免SQL注入风险:

List<Long> list = new ArrayList<>();
list.add(123458686L);
list.add(585858424L);
list.add(688584241L);

// 生成对应数量的占位符
String placeholders = list.stream().map(id -> "?").collect(Collectors.joining(","));
String sql = "select * from emp where empid=? and empidList in(" + placeholders + ")";

PreparedStatement pstmt = con.prepareStatement(sql);
// 设置第一个empid参数
pstmt.setLong(1, 123458686L);
// 循环设置IN子句的每个ID参数
for (int i = 0; i < list.size(); i++) {
    pstmt.setLong(i + 2, list.get(i));
}

ResultSet rs = pstmt.executeQuery();

方案二:使用Oracle内置函数转换字符串(仅适用于内部可控ID列表)

如果使用Oracle 12c及以上版本,可借助DBMS_UTILITY.COMMA_TO_TABLE函数将逗号分隔的字符串转为表,但此方式若处理外部输入存在SQL注入风险:

List<Long> list = new ArrayList<>();
list.add(123458686L);
list.add(585858424L);
list.add(688584241L);

String empcomm = list.stream().map(String::valueOf).collect(Collectors.joining(","));
// 用内置函数将字符串转成表查询
String sql = "select * from emp where empid=? and empidList in (" +
             "select column_value from table(DBMS_UTILITY.COMMA_TO_TABLE('" + empcomm + "')))";

PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setLong(1, 123458686L);
ResultSet rs = pstmt.executeQuery();

内容的提问来源于stack exchange,提问作者user739115

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 10:00:54