繁体   English   中英

查询在 SQL 开发人员中运行良好,但给出错误消息 = ORA-00905:JDBC 中缺少关键字

[英]Query runs fine in SQL Developer but gives Error Msg = ORA-00905: missing keyword in JDBC

我正在尝试从代码中运行这个 SQL 准备好的语句。

select
    COUNT(*)
from table1 ed, table2 e
where ed.id = e.id
  and e.status_cd = ?
  and ed.active_ind = 1
  and {in}
  and systimestamp < FROM_TZ(cast(ed.end_effective_dt_tm as TIMESTAMP), ?)
  and FROM_TZ(cast(? as TIMESTAMP), ?) between TIMESTAMP ? and TIMESTAMP ?

读取此内容并针对 Oracle 数据库执行的 JDBC 代码读取如下内容:

int parameterIndex = 0;
      stmt.setDouble(
          ++parameterIndex, doubleValue);
stmt.setInClause(
          ++parameterIndex, inClauseColumns.toArray(new InClauseColumn[inClauseColumns.size()]));
      stmt.setString(
          ++parameterIndex, tz_Id); /* Setting time zone for casting ed.end_effective_dt_tm */
      stmt.setString(++parameterIndex, timeFilterColumn);
      stmt.setString(++parameterIndex, tz_Id); // timeFilter
      stmt.setTimestamp(
          ++parameterIndex, new Timestamp(startTime), calculationTimeZone); // startTime
      stmt.setTimestamp(++parameterIndex, new Timestamp(endTime), calculationTimeZone); // endTime
      ResultSet rs = null;
      try {
        while (stmt.hasNext()) {
          rs = stmt.next();
   // do stuff

这会在 JDBC 中产生以下错误:

Error Msg = ORA-00905: missing keyword

但是,当从 SQL 开发人员运行时,相同的查询会从数据库返回预期的行。

示例查询来自 SQL 开发人员:

select
    COUNT(*)
from table1 ed, table2 e
where ed.id = e.id
  and e.status_cd = 854 /*Prameter 1*/
  and ed.active_ind = 1
  and ed.facility_cd in (1.7241194E7) /*in clause parameter 2 */
  and
  systimestamp < FROM_TZ(cast(ed.end_effective_dt_tm as TIMESTAMP), 'America/Chicago' /*parameter 3 */)
  and
  FROM_TZ(cast(e.updt_dt_tm /*parameter 4 */ as TIMESTAMP), 'America/Chicago') /*parameter 5 */
  between
  TIMESTAMP '2021-06-30 02:23:20.0' /*parameter 6 */
  and TIMESTAMP '2021-11-10 18:09:24.774' /*parameter 7 */

有人可以就如何使用 JDBC 提供一些建议吗? 我似乎无法弄清楚这里的问题。 谢谢。

查询问题:

  • 不正确的 in 子句and {in}只是ed.facility_cd in (? )并为每个数组元素设置参数
  • 如果将特定java.sql.Timestamp类型设置为 JDBC 语句,则不需要between TIMESTAMP? and TIMESTAMP? between TIMESTAMP? and TIMESTAMP? 只是between? and? between? and?

数据库结构:

CREATE TABLE TABLE1 (
 ID NUMBER,
 active_ind NUMBER,
 end_effective_dt_tm TIMESTAMP,
 facility_cd FLOAT
);

CREATE TABLE TABLE2 (
 ID NUMBER,
 status_cd FLOAT,
 updt_dt_tm TIMESTAMP
);

工作 JDBC 语句的示例:

    public Long execute(Connection connection) throws SQLException {
        long count = 0L;

        double doubleValue = 854D;
        Double[] inClauseValues = new Double[]{1.7241194E7, 1.7241194E8};
        String tz_Id = "America/Chicago";
        Timestamp startTime = Timestamp.valueOf("2021-06-30 02:23:20.0");
        Timestamp endTime = Timestamp.valueOf("2021-11-10 18:09:24.774");
        String timeFilterColumn = "e.updt_dt_tm";
        String inClauseColumn = "ed.facility_cd";

        String sqlQuery = " select COUNT(*) " +
                " from table1 ed, table2 e " +
                "  where ed.id = e.id " +
                "  and e.status_cd = ? " +
                "  and ed.active_ind = 1 " +
                "  and ? in ( " + Arrays.stream(inClauseValues).map(v -> "?").collect(Collectors.joining(", ")) + " ) " +
                "  and systimestamp < FROM_TZ(cast(ed.end_effective_dt_tm as TIMESTAMP), ? ) " +
                "  and FROM_TZ(cast( ? as TIMESTAMP), ? ) between ? and ? ";

        try (PreparedStatement stmt = connection.prepareStatement(sqlQuery)) {
            int parameterIndex = 0;

            stmt.setDouble(++parameterIndex, doubleValue); // Setting e.status_cd
            stmt.setString(++parameterIndex, inClauseColumn); //Set dynamic column for in cluase
            for (Double value : inClauseValues) { //Setting ed.facility_cd in
                stmt.setDouble(++parameterIndex, value);
            }
            stmt.setString(++parameterIndex, tz_Id); /* Setting time zone for casting ed.end_effective_dt_tm */
            stmt.setString(++parameterIndex, timeFilterColumn); //Setting timeFilterColumn e.updt_dt_tm
            stmt.setString(++parameterIndex, tz_Id); /* Setting time zone for casting e.updt_dt_tm  */
            stmt.setTimestamp(++parameterIndex, startTime); // startTime
            stmt.setTimestamp(++parameterIndex, endTime); // endTime

            try (ResultSet rs = stmt.executeQuery()) {
                while (rs.next()) {
                    count = rs.getLong(1);
                }
            }
        }
        return count;
    }

更新
另一种解决方案,您可以使用动态列预构建查询字符串:

    public Long execute(Connection connection) throws SQLException {
        long count = 0L;

        double doubleValue = 854D;
        Double[] inClauseValues = new Double[]{1.7241194E7, 1.7241194E8};
        String tz_Id = "America/Chicago";
        Timestamp startTime = Timestamp.valueOf("2021-06-30 02:23:20.0");
        Timestamp endTime = Timestamp.valueOf("2021-11-10 18:09:24.774");
        String timeFilterColumn = "e.updt_dt_tm";
        String inClauseColumn = "ed.facility_cd";

        String sqlQuery = " select COUNT(*) " +
                " from table1 ed, table2 e " +
                "  where ed.id = e.id " +
                "  and e.status_cd = ? " +
                "  and ed.active_ind = 1 " +
                "  and " + inClauseColumn + " in ( " + Arrays.stream(inClauseValues).map(v -> "?").collect(Collectors.joining(", ")) + " ) " +
                "  and systimestamp < FROM_TZ(cast(ed.end_effective_dt_tm as TIMESTAMP), ? ) " +
                "  and FROM_TZ(cast( " + timeFilterColumn + " as TIMESTAMP), ? ) between ? and ? ";

        try (PreparedStatement stmt = connection.prepareStatement(sqlQuery)) {
            int parameterIndex = 0;

            stmt.setDouble(++parameterIndex, doubleValue); // Setting e.status_cd
            for (Double value : inClauseValues) { //Setting ed.facility_cd in
                stmt.setDouble(++parameterIndex, value);
            }
            stmt.setString(++parameterIndex, tz_Id); /* Setting time zone for casting ed.end_effective_dt_tm */
            stmt.setString(++parameterIndex, tz_Id); /* Setting time zone for casting e.updt_dt_tm  */
            stmt.setTimestamp(++parameterIndex, startTime); // startTime
            stmt.setTimestamp(++parameterIndex, endTime); // endTime

            try (ResultSet rs = stmt.executeQuery()) {
                while (rs.next()) {
                    count = rs.getLong(1);
                }
            }
        }
        return count;
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM