为什么不能在 FORMAT JSON 存在的情况下将绑定变量从 ojdbc 与 Oracle JSON_ARRAY() 一起使用
Why can't a bind variable be used from ojdbc with Oracle JSON_ARRAY() in the presence of FORMAT JSON
在 Oracle 中,以下查询:
select
json_arrayagg(
json_array(
(select json_arrayagg(json_array(1) format json) from dual) format json,
2
)
format json
)
from dual
生成以下 JSON 文档:
[[[[1]],2]]
当我尝试 运行 使用来自 JDBC 的绑定变量查询时,如下所示:
try (PreparedStatement s = connection.prepareStatement(
"""
select
json_arrayagg(
json_array(
(select json_arrayagg(json_array(?) format json) from dual) format json,
?
)
format json
)
from dual
"""
)) {
s.setInt(1, 1);
s.setInt(2, 2); // This fails
try (ResultSet rs = s.executeQuery()) {
while (rs.next())
System.out.println(rs.getString(1));
}
}
然后我得到:
Exception in thread "main" java.sql.SQLException: Invalid column index
at oracle.jdbc.driver.OraclePreparedStatement.setIntInternal(OraclePreparedStatement.java:4956)
at oracle.jdbc.driver.OraclePreparedStatement.setInt(OraclePreparedStatement.java:4947)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.setInt(OraclePreparedStatementWrapper.java:202)
at org.jooq.testscripts.JDBC.main(JDBC.java:50)
我正在使用这些版本:
- 数据库:Oracle Database 21c 快捷版 21.0.0.0.0 版 - 生产
- ojdbc: com.oracle.database.jdbc:ojdbc11:21.5.0.0
这是一个错误吗?可以解决吗?
在我看来,这是 ojdbc 中的一个错误。解决方法包括:
转换绑定变量
try (PreparedStatement s = connection.prepareStatement(
"""
select
json_arrayagg(
json_array(
(select json_arrayagg(json_array(?) format json) from dual) format json,
cast(? as number) -- cast here
)
format json
)
from dual
"""
)) {
s.setInt(1, 1);
s.setInt(2, 2);
try (ResultSet rs = s.executeQuery()) {
while (rs.next())
System.out.println(rs.getString(1));
}
}
删除绑定参数标记前的 FORMAT JSON
指令
try (PreparedStatement s = connection.prepareStatement(
"""
select
json_arrayagg(
json_array(
(select json_arrayagg(json_array(?) format json) from dual) /* no format json here */,
?
)
format json
)
from dual
"""
)) {
s.setInt(1, 1);
s.setInt(2, 2);
try (ResultSet rs = s.executeQuery()) {
while (rs.next())
System.out.println(rs.getString(1));
}
}
在绑定变量周围使用虚拟表达式
try (PreparedStatement s = connection.prepareStatement(
"""
select
json_arrayagg(
json_array(
(select json_arrayagg(json_array(?) format json) from dual) format json,
nvl(null, ?) -- Dummy expression here
)
format json
)
from dual
"""
)) {
s.setInt(1, 1);
s.setInt(2, 2);
try (ResultSet rs = s.executeQuery()) {
while (rs.next())
System.out.println(rs.getString(1));
}
}
插入一个 null
值,然后用 absent on null
再次删除它
try (PreparedStatement s = connection.prepareStatement(
"""
select
json_arrayagg(
json_array(
(select json_arrayagg(json_array(?) format json) from dual) format json,
null, -- This is ignored
?
absent on null
)
format json
)
from dual
"""
)) {
s.setInt(1, 1);
s.setInt(2, 2);
try (ResultSet rs = s.executeQuery()) {
while (rs.next())
System.out.println(rs.getString(1));
}
}
在 Oracle 中,以下查询:
select
json_arrayagg(
json_array(
(select json_arrayagg(json_array(1) format json) from dual) format json,
2
)
format json
)
from dual
生成以下 JSON 文档:
[[[[1]],2]]
当我尝试 运行 使用来自 JDBC 的绑定变量查询时,如下所示:
try (PreparedStatement s = connection.prepareStatement(
"""
select
json_arrayagg(
json_array(
(select json_arrayagg(json_array(?) format json) from dual) format json,
?
)
format json
)
from dual
"""
)) {
s.setInt(1, 1);
s.setInt(2, 2); // This fails
try (ResultSet rs = s.executeQuery()) {
while (rs.next())
System.out.println(rs.getString(1));
}
}
然后我得到:
Exception in thread "main" java.sql.SQLException: Invalid column index
at oracle.jdbc.driver.OraclePreparedStatement.setIntInternal(OraclePreparedStatement.java:4956)
at oracle.jdbc.driver.OraclePreparedStatement.setInt(OraclePreparedStatement.java:4947)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.setInt(OraclePreparedStatementWrapper.java:202)
at org.jooq.testscripts.JDBC.main(JDBC.java:50)
我正在使用这些版本:
- 数据库:Oracle Database 21c 快捷版 21.0.0.0.0 版 - 生产
- ojdbc: com.oracle.database.jdbc:ojdbc11:21.5.0.0
这是一个错误吗?可以解决吗?
在我看来,这是 ojdbc 中的一个错误。解决方法包括:
转换绑定变量
try (PreparedStatement s = connection.prepareStatement(
"""
select
json_arrayagg(
json_array(
(select json_arrayagg(json_array(?) format json) from dual) format json,
cast(? as number) -- cast here
)
format json
)
from dual
"""
)) {
s.setInt(1, 1);
s.setInt(2, 2);
try (ResultSet rs = s.executeQuery()) {
while (rs.next())
System.out.println(rs.getString(1));
}
}
删除绑定参数标记前的 FORMAT JSON
指令
try (PreparedStatement s = connection.prepareStatement(
"""
select
json_arrayagg(
json_array(
(select json_arrayagg(json_array(?) format json) from dual) /* no format json here */,
?
)
format json
)
from dual
"""
)) {
s.setInt(1, 1);
s.setInt(2, 2);
try (ResultSet rs = s.executeQuery()) {
while (rs.next())
System.out.println(rs.getString(1));
}
}
在绑定变量周围使用虚拟表达式
try (PreparedStatement s = connection.prepareStatement(
"""
select
json_arrayagg(
json_array(
(select json_arrayagg(json_array(?) format json) from dual) format json,
nvl(null, ?) -- Dummy expression here
)
format json
)
from dual
"""
)) {
s.setInt(1, 1);
s.setInt(2, 2);
try (ResultSet rs = s.executeQuery()) {
while (rs.next())
System.out.println(rs.getString(1));
}
}
插入一个 null
值,然后用 absent on null
再次删除它
try (PreparedStatement s = connection.prepareStatement(
"""
select
json_arrayagg(
json_array(
(select json_arrayagg(json_array(?) format json) from dual) format json,
null, -- This is ignored
?
absent on null
)
format json
)
from dual
"""
)) {
s.setInt(1, 1);
s.setInt(2, 2);
try (ResultSet rs = s.executeQuery()) {
while (rs.next())
System.out.println(rs.getString(1));
}
}