在jtds.jar中返回日期错误的数据类型

时间:2012-01-20 06:01:23

标签: java sql-server jdbc jtds

我在MS SQL Server上有一个表,其中一列的数据类型为日期。我正在使用jtds.jar与DB进行JDBC连接。我从Connection获取DatabaseMetaData。在检查DatabaseMetaData中的列时,我观察到了

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

将列类型返回为java.sql.Types.VARCHAR,这是一个字符串而不是日期。但它也会返回

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

键入姓名作为日期。

但是对于Oracle,它将日期数据类型返回为java.sql.Types.DATE

为什么会有这样的差异?

2 个答案:

答案 0 :(得分:4)

这是一个已知的JTDS错误,请参阅http://sourceforge.net/p/jtds/bugs/679/

  

SQLServer Date类型的返回数据类型将作为a返回   varchar的长度为10.这是错误的,它应该返回为   Sql.Date。 int iType = rsMeta.getInt(“DATA_TYPE”);字符串tmp =   rsMeta.getString( “TYPE_NAME”);

答案 1 :(得分:1)

这仍然是jTDS 1.3.1的一个悬而未决的问题。通过直接查询我正在使用的表的SQL Server表目录,并获取表的日期列列表,我能够解决它:

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

获得此列表后,您可以明确检查并查看该列是否为日期类型:

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

所以,我说有一个包含三列的样本表:

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

使用jTDS运行时,此代码将打印以下值:

... 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

这不太理想,但它应该适用于有类似问题的其他人。