2012-05-17 51 views
5

我有一個隨機產生的問題(一次調用千分之一)。 錯誤ORA-01722:無效號碼是在準備好的語句Oracle數據庫中執行SQL更新時以隨機方式生成的。的情況下詳情如下:我無法理解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 

通過跟蹤在DB查詢參數的所有參數都是通過JDBC驅動器正確地傳送除了參數它被值"<C4>^X* U"替換(注意這個值在char'u'之前包含回車!)。我不知道爲什麼

+2

你試圖插入的對象的類型是什麼? toString()返回23410984,但它是一個Integer,Long還是BigDecimal? – 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

我們有類似的問題。我們基於hibernate的java代碼發佈了一個準備好的語句,通過使用aspectJ來填寫所有保存操作的用戶信息和「更改原因」。

在3個單獨的數據庫環境(Oracle 10G)中,這個工作沒有任何問題,但在生產數據庫中,這有時會因ORA-01722錯誤而失敗。只有當數據庫服務器上的CPU負載接近100%時纔會發生這種情況。

在另一個論壇上,我發現了一個關於不通過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%並不聰明。

0

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

我在列的頂部使用了一個UDF,其中數字是預期的,我得到的不是一個數字的不同值。所以該操作無法拋出無效的數字異常。

相關問題