Я не могу понять причину ORA-01722: неверный номер

У меня проблема, которая генерируется случайным образом (один раз между тысячными звонками). Ошибка ORA-01722: недопустимый номер генерируется случайным образом при выполнении обновления sql в подготовленной базе данных Oracle операторов. Подробности дела приведены ниже:

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

при отслеживании параметров запроса в БД все параметры правильно передаются через драйвер JDBC, за исключением параметра 23410984, он был заменен значением "<C4>^X* U" (обратите внимание, что это значение содержит возврат каретки перед символом 'u'!). Я не знаю почему


person user1017344    schedule 17.05.2012    source источник
comment
Какой тип объекта вы пытаетесь вставить? ToString () возвращает 23410984, но это Integer, Long или BigDecimal?   -  person Augusto    schedule 17.05.2012
comment
Каковы возможности statement и result?   -  person Jörn Horstmann    schedule 17.05.2012
comment
Тип объекта длинный, а столбец базы данных - номер   -  person user1017344    schedule 17.05.2012
comment
Я столкнулся с той же проблемой с удалением с предложением IN (). Выполнение подзапроса и недопущение добавления строковых значений в запрос позволяет избежать этой проблемы.   -  person Woody    schedule 09.02.2017


Ответы (4)


Основная причина - это java.sql.SQLException: ORA-01722: invalid number.
Может быть, поле last_case_status_history_id type - это число, но ваш параметр равен нулю

person Mark Yao    schedule 17.05.2012

У нас была аналогичная проблема. Наш Java-код, основанный на гибернации, выдал подготовленный оператор для заполнения информации о пользователе и «причины изменения» для всех операций сохранения с использованием аспектаJ.

В трех отдельных средах баз данных (Oracle 10G) это работало без каких-либо проблем, но в производственной базе данных это иногда приводило к ошибке ORA-01722. Это происходит только тогда, когда загрузка процессора на сервере базы данных близка к 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);
}

Теперь мы изменили код, чтобы сделать явное выражение prepare следующим образом:

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

С тех пор этой проблемы не возникало, даже несмотря на то, что среда оставалась прежней с тем же программным обеспечением и высокой нагрузкой на базу данных.

Я слышал от коллеги, что один из администраторов баз данных мог видеть в журнале, что подготовленный оператор был принят базой данных, но ему не был назначен ЦП. (Имеет смысл, поскольку все процессоры будут заняты при такой высокой нагрузке.) Возможно, выдается просто неправильная ошибка, должна выдаваться ошибка «перегрузки базы данных» или что-то в этом роде. Даже лучше никогда не создавать такую ​​ошибку.

Я предполагаю, что это в первую очередь загрузка базы данных, хотя вообще неразумно позволять загрузке процессора постоянно достигать 100%.

person Pieter VN    schedule 06.09.2012

Я пробовал это:

SELECT DUMP(23410984, 17)
FROM   dual;

и получил это:

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

что практически то же самое, что и у вас. Тип 2 - это NUMBER тип данных.

В документации Oracle говорится о втором параметре функции DUMP():

17 возвращает каждый байт, напечатанный как символ, тогда и только тогда, когда он может быть интерпретирован как печатный символ в наборе символов компилятора - обычно ASCII или EBCDIC. Некоторые управляющие символы ASCII также могут быть напечатаны в форме ^ X. В противном случае символ печатается в шестнадцатеричной системе счисления. Все параметры NLS игнорируются.

Итак, кажется, что иногда значение передается не как внутренний байтовый формат ЧИСЛА, а как строка.

person Szilard Barany    schedule 17.05.2012
comment
Возможно, вам следует быть более точным для значений без отметок времени и использовать setLong(). - person Szilard Barany; 17.05.2012

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

Я использовал UDF в верхней части столбца, где ожидается число, и я получал другое значение, которое не является числом. Таким образом, операция не создает исключение из-за недопустимого числа.

person maxmithun    schedule 07.10.2016