如何通过JDBC-ODBC桥在MS Access中指定空值?

时间:2010-06-10 21:02:57

标签: ms-access jdbc odbc blob jdbc-odbc

我无法使用MS Access(sun.jdbc.odbc.JdbcOdbcDriver)在PreparedStatement上调用setNull

preparedStatement.setNull(index, sqltype). 

有解决方法吗?对于LONGBINARY数据类型,我尝试了以下调用,但都没有工作。

setNull(index, java.sql.Types.VARBINARY)
setNull(index, java.sql.Types.BINARY)
java.sql.SQLException: [Microsoft][ODBC Microsoft Access Driver]Invalid SQL data type
        at sun.jdbc.odbc.JdbcOdbc.createSQLException(JdbcOdbc.java:6957)
        at sun.jdbc.odbc.JdbcOdbc.standardError(JdbcOdbc.java:7114)
        at sun.jdbc.odbc.JdbcOdbc.SQLBindInParameterNull(JdbcOdbc.java:986)
        at sun.jdbc.odbc.JdbcOdbcPreparedStatement.setNull(JdbcOdbcPreparedStatement.java:363)

3 个答案:

答案 0 :(得分:5)

我已经观察使用JDBC 4.1,Java 7,MS Access 2013和JDBC-ODBC桥将null绑定到大多数数据类型“非常好”的答案是这个,我已经内置到jOOQ

switch (sqlType) {
    case Types.BINARY:
    case Types.VARBINARY:
    case Types.LONGVARBINARY:
    case Types.BLOB:
        stmt.setNull(nextIndex(), Types.VARCHAR);
        break;

    default:
        stmt.setString(nextIndex(), null);
        break;
}

答案 1 :(得分:3)

我刚刚对Access 2010数据库中的OLE ObjectLONGBINARY)字段进行了测试,我发现所有这五种变体都允许我指定一个空值作为PreparedStatement使用的参数vanilla JDBC / ODBC Driver={Microsoft Access Driver (*.mdb, *.accdb)}

s.setNull(4, java.sql.Types.LONGNVARCHAR);
s.setNull(4, java.sql.Types.LONGVARCHAR);
s.setNull(4, java.sql.Types.NCHAR);
s.setNull(4, java.sql.Types.NVARCHAR);
s.setNull(4, java.sql.Types.VARCHAR);

特别有趣的是

s.setNull(4, java.sql.Types.LONGVARBINARY);

工作,考虑到当我们从Access数据库中检索OLE Object时,我们得到的 java.sql.Types.LONGVARBINARY根据{ {1}}对象:

ResultSetMetaData

返回:

String SQL;
SQL = "SELECT Photo FROM City WHERE City_ID = 12";
s = conn.createStatement();
s.executeQuery(SQL);
ResultSet rs = s.getResultSet();
ResultSetMetaData rsmd = rs.getMetaData();
String accessTypeName = rsmd.getColumnTypeName(1);
int javaType = rsmd.getColumnType(1);
String javaTypeName = (
        javaType == java.sql.Types.LONGVARBINARY 
            ? "java.sql.Types.LONGVARBINARY" 
            : "some other Type"
        );
System.out.println(String.format("The database-specific type name for this column is '%s'", accessTypeName));
System.out.println(String.format("The SQL type for this column is: %d (%s)", javaType, javaTypeName));

关于ODBC的维基百科文章包括一个history,建议在早期的努力(“SQL / CLI”)成为ISO SQL标准的一部分后,微软基本上分叉了他们自己的版本并最终提出了ODBC。如果是这种情况,那么早期努力遵守“ODBC”标准“可能会遇到与试图符合Microsoft RTF文档”标准“的那些相同的困难:”标准“是Microsoft实施的任何内容,并且受制于由微软自行决定改变。

但是,Microsoft的1995年ODBC白皮书(通过下载链接here提供)始终将“OLE对象”数据类型称为映射到“* BINARY”或“原始”类型(或者,在SQL Server,现已弃用的IMAGE数据类型)。因此,CHAR / BINARY差异似乎不是一些早期的ODBC怪癖的例子。

当然,这个谜团并不新鲜。大约11年前的一个论坛帖子here表明,在JDK 1.4发布后发生了一些变化,就会出现这个问题。

最后,Oracle已声明JDBC-ODBC Bridge“将在JDK 8中删除”(参考:here)。因此,如果没有“官方”解释(或者就此而言是一个解决方案),那么任何一个都将变得越来越不可能。

答案 2 :(得分:1)

当我在where子句中发送带有2个条件的SQL查询时,我看到了类似的错误。需要引用的条件之一。它是varchar格式的数字。 MSSQL服务器要求引用条件,否则我看到了您在问题中遇到的错误。