为什么在有FORMAT JSON的情况下,不能从ojdbc与Oracle JSON_ARRAY()一起使用绑定变量

ejk8hzay  于 2023-11-17  发布在  Oracle
关注(0)|答案(1)|浏览(117)

在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 21 c Express Edition 21.0.0.0.0版-生产
  • ojdbc:com.oracle.database.jdbc:ojdbc11:21.5.0.0

这是一个bug吗?可以解决吗?

rta7y2nd

rta7y2nd1#

在我看来,它曾经是ojdbc中的一个bug。它不再出现在23.3.0.23.09版本中。老版本的ojdbc驱动程序的解决方法包括:

强制转换bind变量

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));
    }
}

字符串

删除bind参数标记前的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));
    }
}

在bind变量周围使用伪表达式

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));
    }
}

相关问题