6

我有一个随机生成的问题(千分之一调用之间的一次)。错误ORA-01722:在准备好的语句 Oracle 数据库中执行 sql update 时以随机方式生成无效数字。案件详情如下:

try {
        connection = getConnection();
        statement = connection.prepareStatement(sql);
        for (int i = 0; i < params.length; i++) {
            if (params[i] instanceof Date) {
                statement.setTimestamp(i + 1, new Timestamp(((Date) params[i]).getTime()));
            } else if (params[i] instanceof java.util.Date) {
                statement.setTimestamp(i + 1, new Timestamp(((java.util.Date) params[i]).getTime()));
            } else {
                statement.setObject(i + 1, params[i]);
            }
            paramsBuilder.append(": " + params[i]);
        }
        if (logger.isInfoEnabled()) {
            logger.info("Query String  [" + sql + "] [" + paramsBuilder + "]");
            logger.info("Query Parameters [" + paramsBuilder + "]");
        }
        result = statement.executeUpdate();
        if (logger.isInfoEnabled()) {
            logger.info(result + " rows affected");
        }
    } catch (SQLException e) {
        if (logger.isInfoEnabled()) {
            String message = "Failed to execute SQL statment [" + sql + "] with parameters [" + paramsBuilder + "]";
            logger.error(message, e);
        }
        throw new DAOException(e);
    }

日志中的值是这样的:

Failed to execute SQL statment [update CUSTOMER_CASE set no_of_ptp=?, no_of_unreached=?,collector_name=? , last_case_status_history_id=?, current_handler=?, handling_start_time=?,due_total_open_amount=?, payment_due_invoice_id =?  where id=?] with parameters [: 0: 0: auto: 5470508: null: null: 0.0: 23410984: 2476739] java.sql.SQLException: ORA-01722: invalid number

通过在 DB 上跟踪查询参数,所有参数都通过 JDBC 驱动程序正确传输,除了参数23410984它被替换为值"<C4>^X* U"(注意这个值在 char 'u' 之前包含回车!)。我不知道为什么

4

5 回答 5

5

关键原因是关于java.sql.SQLException: ORA-01722: invalid number
可能字段last_case_status_history_id类型为数字,但您的参数为空

于 2012-05-17T14:11:45.190 回答
3

我们有一个类似的问题。我们基于 hibernate 的 java 代码发布了一个准备好的语句来使用 aspectJ 为所有保存操作填写用户信息和“更改原因”。

在 3 个独立的数据库环境 (Oracle 10G) 中,这可以正常工作,但在生产数据库中,有时会失败并出现 ORA-01722 错误。这只发生在数据库服务器上的 cpu 负载接近 100% 时。

在另一个论坛上,我发现了一个关于不传递 Long 对象而是明确对 long 原语进行拆箱的建议。在高负载下进行拆箱时,jdbc 驱动程序或数据库本身似乎存在问题(即使这听起来很疯狂)。测试了各种 jdbc 驱动程序,例如 1.4 和 1.6 版本。

有时失败的代码是:

private void execute(final Long userId, final String rfc) {
    Object[] args = new Object[]{ userId, rfc };
    getJdbcTemplate().update("call schema.package.setUserAndRFC(?,?)", args);
}

现在我们更改代码以创建一个显式的preparedStatement,如下所示:

private void execute(final Long userId, final String rfc) {
    getJdbcTemplate().update(prepareStatement(userId.longValue(), rfc));
}

private PreparedStatementCreator prepareStatement(final long userId, final String rfc) {
    return new PreparedStatementCreator() {
        @Override
        public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
            PreparedStatement statement = con.prepareStatement("call schema.package.setUserAndRFC(?,?) ");
            statement.setLong(1, userId);
            statement.setString(2, rfc);
            return statement;
        }
    };
}

从那以后,这个问题就没有发生过,即使环境保持不变,使用相同的软件和数据库的高负载也是如此。

我从一位同事那里听说,其中一位 DBA 可以在日志中看到准备好的语句已被数据库接受,但没有为其分配 cpu。(这是有道理的,因为所有 cpu 都会在如此高的负载下忙碌。)可能只是抛出了错误的错误,应该抛出某种“数据库过载”错误或其他东西。更好的是无论如何都不要产生这样的错误。

我想这主要是数据库负载,让 cpu 负载一直达到 100% 一点也不聪明。

于 2012-09-06T08:57:08.183 回答
2

我试过这个:

SELECT DUMP(23410984, 17)
FROM   dual;

得到了这个:

Typ=2 Len=5: c4,^X,*,^J,U

这实际上和你得到的一样。类型 2 是NUMBER数据类型。

Oracle 文档说明了DUMP()函数的第二个参数:

当且仅当它可以在编译器的字符集中(通常是 ASCII 或 EBCDIC)被解释为可打印字符时,17 将每个字节打印为一个字符。一些 ASCII 控制字符也可以以 ^X 的形式打印。否则,字符将以十六进制表示法打印。所有 NLS 参数都被忽略。

因此,有时该值似乎不是作为 NUMBER 的内部字节格式而是作为字符串传输的。

于 2012-05-17T14:14:21.277 回答
0

java.sql.SQLException: ORA-01722: invalid number.

我在需要一个数字的列顶部使用 UDF,我得到一个不同的值,它不是一个数字。所以操作失败,抛出无效数字异常。

于 2016-10-07T05:27:40.547 回答
0

有时,当我们使用 IN 子句并将值作为 IN ('1, 2, 3, 4') 传递而不是按照以下方式传递时 IN ('1','2','3','4 ')

于 2022-01-06T10:03:28.637 回答