4

我无法使用 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]无效的 SQL 数据类型
        在 sun.jdbc.odbc.JdbcOdbc.createSQLException(JdbcOdbc.java:6957)
        在 sun.jdbc.odbc.JdbcOdbc.standardError(JdbcOdbc.java:7114)
        在 sun.jdbc.odbc.JdbcOdbc.SQLBindInParameterNull(JdbcOdbc.java:986)
        在 sun.jdbc.odbc.JdbcOdbcPreparedStatement.setNull(JdbcOdbcPreparedStatement.java:363)
4

3 回答 3

5

The answer that I have observed to work "quite well" for binding null to most data types with JDBC 4.1, Java 7, MS Access 2013 and the JDBC-ODBC bridge is this one, which I've built into 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;
}
于 2013-10-31T17:13:59.373 回答
3

我刚刚对此进行了测试,对于 Access 2010 数据库中的OLE Object( LONGBINARY) 字段,我发现所有这五个变体都允许我使用 vanilla JDBC/ODBC 将 null 值指定为 PreparedStatement 的参数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.LONGVARBINARYResultSetMetaData

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

返回:

The database-specific type name for this column is 'LONGBINARY'
The SQL type for this column is: -4 (java.sql.Types.LONGVARBINARY)

关于 ODBC 的 Wikipedia 文章包含一段历史,表明在早期的努力(“SQL/CLI”)成为 ISO SQL 标准的一部分之后,微软基本上分叉了他们自己的版本并最终提出了 ODBC。如果是这样的话,那么符合“ODBC‘标准’”的早期努力可能会面临与试图符合微软的 RTF 文档“标准”相同的困难:“标准”是微软实施的任何东西,并且受制于Microsoft 自行决定更改。

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

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

最后,Oracle 声明 JDBC-ODBC 桥“将在 JDK 8 中删除”(参考:此处)。因此,如果没有“官方”解释(或修复,就此而言),任何人都不太可能出现。

于 2013-10-31T19:21:13.180 回答
1

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

于 2011-06-23T19:43:59.500 回答