Welcome to MSDN Blogs Sign in | Join | Help

Microsoft JDBC Driver Team Blog

Discussions related to Microsoft JDBC driver.
Use execute() and getMoreResults() methods for those pesky complex SQL queries

Per JDBC spec, the Statement.executeUpdate() and Statement.executeQuery() methods are to be used only with queries that produce a single update count or result set, respectively.  If you need to execute multiple SQL statements in a single query, perhaps through a stored procedure call, then you should use Statement.execute() to execute the query and Statement.getMoreResults() to process all of the results.  However, in my not so humble opinion, the execute() and getMoreResults() methods aren’t exactly simple to use properly.  For example, execute() and getMoreResults() return false when the result is an update count.  But they also return false when there are no more results.  Ok, so how do you tell whether you have an update count or no more results?  You need to check the return value from a subsequent call to Statement.getUpdateCount() or Statement.getResultSet().  One way to process all results (including errors) from a complex query would be to use code like this:

 

            CallableStatement cs = con.prepareCall("{call myStoredProc()}");

 

            int resultNum = 0;

            while (true)

            {

                boolean queryResult;

                int rowsAffected;

 

                if (1 == ++resultNum)

                {

                    try

                    {

                        queryResult = cs.execute();

                    }

                    catch (SQLException e)

                    {

                        // Process the error

                        System.out.println("Result " + resultNum + " is an error: " + e.getMessage());

 

                        // When execute() throws an exception, it may just be that the first statement produced an error.

                        // Statements after the first one may have succeeded.  Continue processing results until there

                        // are no more.

                        continue;

                    }

                }

                else

                {

                    try

                    {

                        queryResult = cs.getMoreResults();

                    }

                    catch (SQLException e)

                    {

                        // Process the error

                        System.out.println("Result " + resultNum + " is an error: " + e.getMessage());

 

                        // When getMoreResults() throws an exception, it may just be that the current statement produced an error.

                        // Statements after that one may have succeeded.  Continue processing results until there

                        // are no more.

                        continue;

                    }

                }

 

                if (queryResult)

                {

                    ResultSet rs = cs.getResultSet();

 

                    // Process the ResultSet

                    System.out.println("Result " + resultNum + " is a ResultSet: " + rs);

 

                    rs.close();

                }

                else

                {

                    rowsAffected = cs.getUpdateCount();

 

                    // No more results

                    if (-1 == rowsAffected)

                    {

                        --resultNum;

                        break;

                    }

 

                    // Process the update count

                    System.out.println("Result " + resultNum + " is an update count: " + rowsAffected);

                }

            }

 

            System.out.println("Done processing " + resultNum + " results");

 

Remember: to execute a complex query with a mix of DDL, DML and result sets, and possible errors, always use execute() to execute the query and use getUpdateCount(), getResultSet(), and getMoreResults() to process the results.

 

--David Olix [SQL Server]

This post is provided 'as is' and confers no express or implied warranties or rights.

Posted: Friday, August 01, 2008 11:04 AM by dpblogs

Comments

Microsoft JDBC Driver Team Blog said:

If you are using executeUpdate() to execute a query or stored procedure containing multiple SQL statements,

# August 4, 2008 6:43 PM

Mike Arney said:

For stored procedures, where do the return value and output parameters fit into this picture?

Thanks,

Mike

# August 5, 2008 11:39 AM

George said:

For the record, if you've just got a normal Statement (which might include several SQL selects/inserts/updates/etc.), then it appears you can just do the following with one .execute(String sql):

Statement stmt = con.createStatement();

try {

boolean hasResults = stmt.execute(sql);

do {

if (hasResults) printResults(stmt.getResultSet(),"\t");

else System.out.printf("%d rows affected\n\n", stmt.getUpdateCount());

hasResults = stmt.getMoreResults();

} while (hasResults || stmt.getUpdateCount() != -1);

} catch (Exception e) {

System.err.println("Error with: " + sql);

e.printStackTrace();

} finally {

stmt.close();

}

# September 26, 2008 10:20 AM

Microsoft JDBC Driver Team Blog said:

If you've ever encountered this error with the Microsoft SQL Server JDBC Driver, you may be left scratching

# February 25, 2009 9:00 PM

Norbert said:

Thanks. Your explaination helped figuring out what was going wrong with part of our code. Actually, what I've been reading elsewhere on the net is not as accurate as your account. I'd still optimize the Java code a bit, but still great work. Thanks for posting.

-Norb

# May 11, 2009 11:40 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

  
Enter Code Here: Required

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Page view tracker