【问题标题】:ResultSet.next() causes SQLServerException: Conversion failed when converting the nvarchar value 'NM21' to data type intResultSet.next() 导致 SQLServerException:将 nvarchar 值“NM21”转换为数据类型 int 时转换失败
【发布时间】:2017-05-25 03:06:48
【问题描述】:

我正在尝试制作一个可以接受来自客户端的查询、查找匹配记录并返回相关信息的服务器。这里有很多代码,但最相关的部分是方法getProduct(String code)。我包含了尽可能多的连接信息,以防您想查看,但我的测试查询适用于此连接。我的测试查询是:

ResultSet a = statement.executeQuery("SELECT TOP 10 Code, [name in english], NetSalesPrice, PriceList1 FROM [REDACTED]");

class PCServer {
Connection dataConn;
public static void main(String[] args){
    new PCServer();
}
public PCServer(){
    try{
        Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
        dataConn = DriverManager.getConnection([REDACTED]);
        System.out.println("REPORT: Connected to Database");
        ServerSocket ss = new ServerSocket([REDACTED]);
        Socket cs = null;
        while(true){
            cs = ss.accept();
            ThreadServer ts = new ThreadServer(cs, this);
            ts.start();
        }
    }catch(SQLException sqle){
        sqle.printStackTrace();
    }catch(ClassNotFoundException cnfe) {
        cnfe.printStackTrace();
    }catch(IOException ioe){
        ioe.printStackTrace();
    }
}

public String getProduct(String code){
    System.out.println("REPORT from PCS.getProduct(): code == "+ code);
    String query = "SELECT Code, [name in english], NetSalesPrice, PriceList1 FROM [REDACTED] WHERE Code=";
    query = query.concat(code);
    System.out.println("REPORT from PCS.getProduct(): Query: "+ query);

    String productDescription = code+":Not:Found";
    try{
        Statement s = dataConn.createStatement();
        ResultSet rs = s.executeQuery(query);
        if(rs.isBeforeFirst()) {
            System.out.println("REPORT from PCS.getProduct(): rs.isBeforeFirst == true");
            rs.next(); //This is throwing com.microsoft.sqlserver.jdbc.SQLServerException: Conversion Failed...
            productDescription = rs.getString(1) + ":" + rs.getString(2) + ":$" + rs.getString(3);
        }
    }catch (SQLException sqle){
        System.out.println("SQL Server Exception in getProduct(String code)");
        sqle.printStackTrace();
    }

    return productDescription;
}

在创建或访问 ResultSet 时,异常似乎是数据类型错误或 NumberFormatException 的结果。但是,我尝试将代码转换为 int,即使注释掉 productDescription = rs.getString(1) + ":" + rs.getString(2) + ":$" + rs.getString(3); 行,错误仍然存​​在。我确信rs.next() 正在引发错误。此外,我们知道 rs 不为空,因为我们检查了rs.isBeforeFirst(),如果 ResultSet 为空,它将返回 false。

这是完整的消息

com.microsoft.sqlserver.jdbc.SQLServerException: Conversion failed when converting the nvarchar value 'NM21' to data type int.
   at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216)
   at com.microsoft.sqlserver.jdbc.SQLServerResultSet$FetchBuffer.nextRow(SQLServerResultSet.java:4853)
   at com.microsoft.sqlserver.jdbc.SQLServerResultSet.fetchBufferNext(SQLServerResultSet.java:1781)
   at com.microsoft.sqlserver.jdbc.SQLServerResultSet.next(SQLServerResultSet.java:1034)
   at PCServer.getProduct(PCServer.java:83)
   at PCServer$ThreadServer.run(PCServer.java:128)

我知道这个问题看起来与其他问题相似。关于这个错误还有很多其他帖子,但ResultSet.next()没有一个是抛出的

【问题讨论】:

    标签: java mysql sql-server jdbc


    【解决方案1】:

    我已经想通了,结果证明这是一个非常愚蠢的错误。但是https://xkcd.com/979/ 教会了我不要放弃我的问题。

    我的查询需要在代码周围加上单引号。所以应该是:

    statement.executeQuery("SELECT Code, [name in english], NetSalesPrice, PriceList1 FROM ERPLY_ITEMS WHERE Code='"+code+"'") 而不是:

    statement.executeQuery("SELECT Code, [name in english], NetSalesPrice, PriceList1 FROM ERPLY_ITEMS WHERE Code="+code)

    我很尴尬地忽略了这一点。 This answer 对于一个关于使用 WHERE 子句的程序生成查询的问题,连接是一种非常容易受到攻击的查询生成方法。相反,Isaac 建议使用 Prepared Statements 以编程方式生成查询。

    我希望这最终会对某人有所帮助。

    【讨论】:

    • 您根本不应该将值连接到查询中,您应该使用带有参数占位符的准备好的语句。您当前的代码(和您的解决方案)容易受到 SQL 注入的攻击。
    • 我在另一个问题中看到了,这就是我包含最后一段的原因。我只是想解释我遇到的问题。但我已经改变了我的程序以使用准备好的语句,而不是连接。
    猜你喜欢
    • 2020-04-17
    • 2011-08-29
    • 2015-06-20
    • 2016-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多