2012-05-17 32 views
5

Tôi gặp sự cố được tạo ngẫu nhiên (một lần giữa nghìn cuộc gọi). Lỗi ORA-01722: số không hợp lệ được tạo theo cách ngẫu nhiên trong khi thực hiện cập nhật sql trong cơ sở dữ liệu Oracle đã được chuẩn bị sẵn sàng. Các chi tiết trường hợp như sau:Tôi không thể hiểu lý do đằng sau ORA-01722: số không hợp lệ

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

và giá trị trong nhật ký là như thế:

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 

bằng cách lần theo các thông số truy vấn ở DB tất cả các thông số được chuyển giao một cách chính xác thông qua các trình điều khiển JDBC trừ tham số nó đã được thay thế bằng giá trị "<C4>^X* U" (lưu ý giá trị này có chứa vận chuyển trở lại trước khi char 'u'!). Tôi không biết tại sao

+2

Loại đối tượng bạn đang cố gắng chèn là gì? Các toString() trả về 23410984, nhưng nó là một Integer, Long hoặc BigDecimal? – Augusto

+0

Phạm vi của 'câu lệnh' và' kết quả' là gì? –

+0

Kiểu đối tượng dài và cột cơ sở dữ liệu là số – user1017344

Trả lời

4

Lý do chính là khoảng java.sql.SQLException: ORA-01722: invalid number.
Có thể là lĩnh vực last_case_status_history_id loại là số, nhưng thông số của bạn là null

2

Tôi cố gắng này:

SELECT DUMP(23410984, 17) 
FROM dual; 

và nhận điều này:

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

đó là thực tế giống như những gì bạn có. Loại 2 là NUMBER loại dữ liệu.

Oracle tài liệu nói cho tham số thứ hai của DUMP() chức năng:

17 lợi nhuận mỗi byte in như một nhân vật khi và chỉ khi nó có thể được hiểu như là một nhân vật có thể in được trong bộ ký tự của trình biên dịch-thường ASCII hoặc EBCDIC. Một số ký tự điều khiển ASCII cũng có thể được in dưới dạng^X. Nếu không thì ký tự được in theo ký hiệu thập lục phân. Tất cả các tham số NLS đều bị bỏ qua.

Vì vậy, có vẻ như đôi khi giá trị được chuyển không phải là định dạng byte nội bộ của NUMBER mà là chuỗi.

+1

Có lẽ bạn nên rõ ràng hơn cho các giá trị không dấu thời gian và sử dụng 'setLong()'. –

2

Chúng tôi gặp sự cố tương tự. Mã java dựa trên hibernate của chúng tôi đã ban hành một câu lệnh chuẩn bị để điền vào thông tin người dùng và 'lý do thay đổi' cho tất cả các hoạt động lưu bằng cách sử dụng aspectJ.

Trong 3 môi trường cơ sở dữ liệu riêng biệt (Oracle 10G), nó hoạt động mà không có bất kỳ vấn đề nào, nhưng trên cơ sở dữ liệu sản xuất đôi khi thất bại với lỗi ORA-01722. Điều này chỉ xảy ra khi tải CPU trên máy chủ cơ sở dữ liệu gần 100%.

Trên một diễn đàn khác, tôi đã tìm thấy một đề xuất về việc không truyền dọc các đối tượng Long nhưng thực hiện unboxing một cách rõ ràng với nguyên thủy dài. Có vẻ như trình điều khiển jdbc hoặc cơ sở dữ liệu chính nó có vấn đề khi làm unboxing này trên tải cao (ngay cả khi điều đó nghe có vẻ khá điên rồ). Các trình điều khiển jdbc khác nhau đã được kiểm tra, chẳng hạn như các phiên bản 1.4 và 1.6.

Mã mà đôi khi thất bại là:

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

Bây giờ chúng ta đã thay đổi mã để thực hiện một PreparedStatement rõ ràng như thế này:

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

Vấn đề này đã không xảy ra kể từ khi, ngay cả khi môi trường ở tương tự với cùng một phần mềm và tải cao trên cơ sở dữ liệu.

Tôi đã nghe từ một đồng nghiệp rằng một trong các DBA có thể thấy trong nhật ký rằng câu lệnh chuẩn bị đã được cơ sở dữ liệu chấp nhận, nhưng không có CPU nào được gán cho nó. (Làm cho tinh thần vì tất cả các CPU sẽ bận rộn trên một tải cao như vậy.) Nó có thể chỉ đơn giản là lỗi sai được ném ra, một lỗi 'quá tải cơ sở dữ liệu' của một số loại nên được ném hoặc một cái gì đó. Thậm chí tốt hơn sẽ không bao giờ tạo ra một lỗi như vậy anyway.

Tôi đoán nó chủ yếu là tải cơ sở dữ liệu mặc dù, nó không phải là thông minh ở tất cả để cho tải CPU đạt 100% tất cả các thời gian.

0

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

Tôi đã sử dụng UDF ở trên cùng của cột nơi một số được mong đợi và tôi đã nhận được một giá trị khác không phải là số. Vì vậy, các hoạt động không ném một ngoại lệ số không hợp lệ.

Các vấn đề liên quan