Java.sql.SQLException: [Microsoft][ODBC Driver Manager]无效的描述符索引。

7
我使用以下代码。
try {
    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
    Connection con = DriverManager.getConnection("jdbc:odbc:access");
    String sql = "Select * from table";
    Statement stmt = con.createStatement();
    ResultSet rs = stmt.executeQuery( sql );
    ResultSetMetaData md = rs.getMetaData();
    int columns = md.getColumnCount();
    for (int i = 1; i <= columns; i++) {
        columnNames.addElement( md.getColumnName(i) );
    }
    while (rs.next()) {
        Vector row = new Vector(columns);
        for (int i = 1; i <= columns; i++){
            row.addElement( rs.getObject(i) );
        }
        data.addElement( row );
    }
    rs.close();
    stmt.close();
}catch(Exception e){
    System.out.println(e);
}

它显示:
java.sql.SQLException:[Microsoft][ODBC Driver Manager] Invalid descriptor index

这是什么原因导致的,我该如何解决?

它确切地在哪一行被抛出了?您可以在堆栈跟踪的第一行中找到行号。异常表明您正在尝试访问结果集中错误/未知的列。但是,您问题中的代码片段并没有透露这一点。 - BalusC
1
感谢代码更新。但是异常处理非常差。请将System.out.println(e)这一行替换为e.printStackTrace()或者只是throw e。这样你就可以获得完整的堆栈跟踪信息,并且可以了解发生问题的行号。 - BalusC
6个回答

19

我曾经遇到过完全相同的错误,这是由Delphi ODBC Express驱动程序引起的。

我找到的解决方法是:

在您的选择查询语句的末尾放置varchar(max)和/或varbinary(max)字段。(表定义中的顺序无关紧要。)

这对我们来说真的解决了问题,想与大家分享。


10

我怀疑异常并非由贴出的代码中的某行引起。我有我的理由这样说。

"无效描述符索引(Invalid descriptor index)"的SQLException通常在您不正确读取结果集时获取。此情况可能以多种方式表现:

  • 按顺序读取列。恐怕,一些JDBC驱动程序要求您按顺序读取列,从第一列开始。这是一些驱动程序编写的方式;在读取生成的结果集时不能跳过任何列,因为驱动程序实际上正在读取流并将流中的对象转换为JDBC类型的对象。
  • 您可能正在读取一个索引无效或列名与结果集中返回的任何列都不匹配的列。简单的解决方法是修复查询以返回所需列,或修复代码以不读取缺失的列。

如果您需要解决此问题,则需要知道上述哪个条件在您的代码中为真,并相应地进行更正。


我尝试将我的SQL语句列出为:"SELECT RoomID, RoomName, RoomSize, Floor From tblRoom"。这次它没有显示错误消息,但它不会在我的JTable中生成结果。 - Tepken Vannkorn
@Tepken,这是否与“SELECT * FROM tblRoom”相同?即tblRoom中有4列吗? - Vineet Reynolds
当然是的。我从其他资源中搜索并得知了这件事。 - Tepken Vannkorn
奇怪。我认为你可以向微软发送一个漏洞报告账单。 - Vineet Reynolds
3
“Reading columns out of sequence…” 我在我的情况下更改了这个,喝了一杯咖啡,杀了一只鸡,然后像魔术般所有问题都解决了。谢谢。 - ian_scho
@ian_scho:这是我典型的SQL Server故障排除工作流程。 - BenDundee

7

我多年来使用ODBC驱动程序和PHP时,了解到这个bug。尝试将文本和图像列放在选择列表的末尾。
不要使用:

select * from t

但要严格列举
select plain_column1, plain_column2, .... image_column from t

不幸的是,微软一直在修复这个漏洞。JDBC驱动程序工作正常。


相反在我的情况下起作用了,以前我传递的查询是 select plain_column1, plain_column2, .... image_column from t,这会导致错误,但当我将查询更改为 select * from t 时,异常得到解决。 - Shams

1

我遇到了一个错误

SEVERE: null java.sql.SQLException: [Microsoft][SQL Server Native Client 10.0]无效的描述符索引

代码如下

String sqlStr = "select soldItems.payment as aa, Sysuser.name as sname, Books.Name as abookName, soldItems.Qunt as qunt, soldItems.date as soldBooks from Sysuser inner join soldItems on soldItems.CustomerId=Sysuser.id inner join Books on Books.bookId=soldItems.bookId where CustomerId='" + cusId + "' and PaymentDone is NULL";
    System.out.println(sqlStr);
    DbConnection con = new DbConnection();
    con.getConnection();
    ResultSet rs = con.getData(sqlStr);
    while (rs.next()) {
        int i = 0;


        dataArry[i][0] = rs.getString("abookName");
        dataArry[i][1] = rs.getString("qunt");
         dataArry[i][2] = rs.getString("aa");
        dataArry[i][3] = rs.getString("soldBooks");

        i++;
    }

"修复方法是将 rs.getString 放在与 SQL 相同的顺序中。 因此,代码需要是:"
       dataArry[i][2] = rs.getString("aa");
        dataArry[i][0] = rs.getString("abookName");
        dataArry[i][1] = rs.getString("qunt");

        dataArry[i][3] = rs.getString("soldBooks");

1

我用例子解释了@Remco的答案,它简单易懂,帮助我解决了我的问题。首先找到MYTABLE的列信息,并将列放在最后,具有最大值(假设是varchar(max)和/或varbinary(max))。请尝试下面的示例。

出现错误

library(DBI)
library(ODBC)
myquery<- dbGetQuery(con,"SELECT * FROM MYTABLE")

Error in Result_fetch....:  Invalid Descriptor Index

解决方案

dbcolumnInfo(dbSendWuery(con,"SELECT * FROM MYTABLE")

dbcolumninfo() 的输出结果

DateTimeSampled 的结果可以看出它是 varchar(max) 类型的。使用以下查询将这一列放在 MYTABLE 的末尾。

myquery<- dbGetQuery(con,"SELECT [PROCHI],[hb_extract],
[QuantityValue],[QuantityUnit],[Interpretation],
[LabNumber],[LocalClinicalCodeValue],[DateTimeSampled]
FROM MYTABLE")

用R轻松学习SQL


1
如果您尝试在索引值为0的位置获取结果集变量值,就会发生这种情况。例如:考虑一个具有5列的表:
ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName);
while(rs.next())
{
   for(int i=0;i<5;i++)
   //This will throw the exception
   System.out.println(rs.getString(i)); //Since the value will be returned from 1 not 0
   //The below code was the right way
   System.out.println(rs.getString(i+1));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接