2012-05-17 3 views
5

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

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'!). Не знаю почему

+2

Каков тип объекта, который вы пытаетесь вставить? ToString() возвращает 23410984, но является ли он целым, длинным или большим децималом? – Augusto

+0

Какова область действия 'statement' и' result'? –

+0

Тип объекта длинный, а столбец базы данных - номер – user1017344

ответ

4

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

2

Я попытался это:

SELECT DUMP(23410984, 17) 
FROM dual; 

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

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

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

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

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

Таким образом, кажется, что иногда значение передается не как внутренний формат байта NUMBER, а как строка.

+1

Возможно, вы должны быть более явным для значений без отметки времени и использовать 'setLong()'. –

2

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

В трех отдельных средах баз данных (Oracle 10G) это работало без каких-либо проблем, но в производственной базе данных это иногда не удавалось с ошибкой ORA-01722. Это происходит только тогда, когда загрузка процессора на сервере базы данных близка к 100%.

На другом форуме я нашел предложение о том, чтобы не проезжать по длинным объектам, но явно опуская ящик на длинный примитив. Кажется, что драйвер jdbc или сама база данных имеют проблемы при выполнении этого unboxing при высокой нагрузке (даже если это звучит довольно сумасшедшим). Были протестированы различные драйверы 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; 
     } 
    }; 
} 

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

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

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

0

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

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

Смежные вопросы