为什么不能在 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)

我正在使用这些版本:

这是一个错误吗?可以解决吗?

在我看来,这是 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));
    }
}