2012-01-20 28 views
7

Tôi có một bảng trên MS SQL Server với một cột có kiểu dữ liệu là ngày tháng. Tôi đang sử dụng jtds.jar cho kết nối JDBC với DB. Tôi đang lấy DatabaseMetaData từ kết nối. Khi kiểm tra các cột từ DatabaseMetaData, tôi quan sát thấy rằngLoại dữ liệu sai được trả về ngày trong jtds.jar

int iType = rsMeta.getInt("DATA_TYPE"); 

trả về Kiểu cột là java.sql.Types.VARCHAR là một chuỗi và không có ngày tháng. nhưng nó cũng trả lại

String tmp = rsMeta.getString("TYPE_NAME"); 

nhập tên là ngày.

Nhưng đối với Oracle, Nó trả về kiểu dữ liệu ngày là java.sql.Types.DATE.

Tại sao sự khác biệt như vậy?

+0

lý do tại sao bạn không sử dụng '.getTimestamp (" DATA_TYPE ")' – epoch

+0

Theo kiến ​​thức của tôi getInt ("DATA_TYPE") phải trả về một trong các loại từ http://docs.oracle.com/javase/1.4 .2/docs/api/constant-values.html # java.sql.Types.DATE – FlyingDutchman

+2

Tôi cũng tìm thấy liên kết tương tự: http://stackoverflow.com/questions/7885459/jdbc-jtds-bug-for-columns- kiểu-date-and-timex – FlyingDutchman

Trả lời

4

Đây là lỗi JTDS đã biết, xem http://sourceforge.net/p/jtds/bugs/679/.

Các kiểu dữ liệu trở lại cho một loại SQLServer ngày được trả về như một varchar với chiều dài 10 Đây là sai, nó sẽ trả về như Sql.Date. int iType = rsMeta.getInt ("DATA_TYPE"); Chuỗi tmp = rsMeta.getString ("TYPE_NAME");

1

Điều này dường như vẫn là vấn đề mở với jTDS 1.3.1. Tôi đã có thể làm việc xung quanh nó bằng cách truy vấn catalogue SQL Server bảng trực tiếp cho các bảng Tôi đang làm việc với, và nhận được một danh sách các cột ngày cho bảng:

private HashMap<String,Boolean> getDateColumns (String tableName, String schemaName, Connection conn) throws Exception { 
    String sql = "SELECT table_name + ',' + column_name" 
       + " FROM INFORMATION_SCHEMA.COLUMNS " 
       + " WHERE TABLE_SCHEMA = N'" + schemaName + "' " 
       + " AND table_name = N'" + tableName + "' " 
       + " AND data_type IN ('date', 'datetime', 'datetime2')"; 

    Statement stmt = conn.createStatement();       
    ResultSet rs = stmt.executeQuery(sql); 
    HashMap<String,Boolean> dateCols = new HashMap<String,Boolean>(); 

    while (rs.next()) { 
     String tableColKey = rs.getString(1);   
     dateCols.put(tableColKey.toUpperCase(), true); 
    } 

    rs.close();  
    return dateCols;   
} 

Một khi bạn có danh sách này, bạn có thể một cách rõ ràng kiểm tra và xem nếu cột là một loại date:

private ResultSetMetaData getTableMetaData (String tableName, Connection conn) throws Exception { 
    String sql = "SELECT * FROM dbo." + tableName + " where 1 = 2 "; 
    Statement stmt = conn.createStatement();       
    ResultSet rs = stmt.executeQuery(sql); 
    ResultSetMetaData rsmd = rs.getMetaData(); 
    rs.close(); 

    HashMap<String,Boolean> dateColumns = getDateColumns (tableName, conn); 

    for (int i = 1; i <= rsmd.getColumnCount(); i++) {     

     String key = tableName + "," + rsmd.getColumnName(i); 
     int type = -1; 
     if (dateColumns.containsKey(key)) { 
      type = Types.DATE; 
     } 
     else { 
      type = rsmd.getColumnType(i); 
     } 

     System.out.println ("... col: " + rsmd.getColumnName(i) + ", driver type name: " + rsmd.getColumnTypeName(i) + ", driver type: " + rsmd.getColumnType(i) + ", final data type: " + type); 
    }  

    return rsmd; 
} 

Vì vậy, nói rằng tôi có một bảng mẫu với ba cột:

SAMPLE 
------------------ 
SITE_ID  numeric 
START_DATE date 
END_DATE date 

mã này sẽ in các giá trị sau khi chạy với JT DS:

... col: SITE_ID, driver type name: numeric, driver type: 2, final data type: 2 
... col: START_DATE, driver type name: nvarchar, driver type: 12, final data type: 91 
... col: END_DATE, driver type name: nvarchar, driver type: 12, final data type: 91 

Nó không lý tưởng, nhưng nó sẽ làm việc cho những người khác có vấn đề tương tự.