10

My jdbc driver for mysql db is of version 5.1.25.

I want to execute sql query like so:

statement.execute("select fullName from user where user_id=1; select fullName from user where user_id=2");

And I always receive exception:

Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select fullName from user where user_id=2' at line 1
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.Util.getInstance(Util.java:386)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4187)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4119)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2731)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2809)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2758)
    at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:894)
    at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:732)
    at dbViewer.model.UserConnectionManager.retrieveRoutinesNames1(UserConnectionManager.java:622)
    at dbViewer.model.UserConnectionManager.main(UserConnectionManager.java:637)

BUT when I run this same query(separated by semicolon) from command line it works perfectly and outputs two tables as expected.

Gord Thompson
  • 116,920
  • 32
  • 215
  • 418
Volodymyr Levytskyi
  • 3,364
  • 9
  • 46
  • 83
  • Probably not - the sql would return two result sets, what is going to be returned by execute()? Presumably it all works OK if you just have a single statement? – Dave Richardson Aug 29 '13 at 16:07
  • Disallowing multiple statements in one query is also a security safeguard, albeit not a perfect one. If you could execute multiple queries, injection could let an intruder execute completely arbitrary SQL: http://xkcd.com/327 . You should do `select fullName from user WHERE user_id=1 OR user_id=2`. You should also use prepared statements, for efficiency and safety against SQL injection. – yshavit Aug 29 '13 at 17:06

3 Answers3

18

Using ; in a query for most databases doesn't work as it is usually not part of the statement syntax itself, but a terminator for command line or script input to separate statements. The command line or script processor sees a semi-colon as the signal that the statement is complete and can be sent to the server.

Also in JDBC a single statement prepare (or execute) should only be one actual statement so multiple statements are not allowed and so there is also no need to have a semi-colon, and as for some (most?) databases the semi-colon isn't part of the statement syntax, it is simply a syntax error to have one included.

If you want to execute multiple statements, you need to use separate executes. Technically, MySQL does have an option to support multiple executions which can be enabled by a connection property. This behavior is not compliant with the JDBC specification/API and makes your code less portable. See allowMultiQueries on Driver/Datasource Class Names, URL Syntax and Configuration Properties for Connector/J

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
12

I want to execute sql query like so:

statement.execute("select fullName from user where user_id=1; select fullName from user where user_id=2");

This is possible only when you have set one database connection property to allow multiple queries to execute all at once. And the property name is allowMultiQueries=true. This property has to be set and send along with a database connection request to the server. General syntax is like this:

String dbUrl = "jdbc:mysql:///test?allowMultiQueries=true";

This is additional connection property to those if already exists some, like autoReConnect=true, etc.

Acceptable values for allowMultiQueries property are true, false, yes, and no. Any other value is rejected at runtime with an SQLException.

You have to use execute( String sql ) or its other variants to fetch results of the query execution.

multiQuerySqlString =  "select fullName from user where user_id=1; ";
multiQuerySqlString += "select fullName from user where user_id=2; ";
// you can multiple types of result sets
multiQuerySqlString += "select last_login from user_logs where user_id=1; ";

boolean hasMoreResultSets = stmt.execute( multiQuerySqlString );

To iterate through and process results you require following steps:

int rsNumber = 0;
while ( hasMoreResultSets ) {  
    rsNumber += 1;
    Resultset rs = stmt.getResultSet();

    // based on the structure of the result set,
    // you can handle column values.
    if ( rsNumber == 1 ) {
      while( rs.next() ) {
          // handle your rs here
      } // while rs
    } // if rs is 1
    else if ( rsNumber == 2 ) {
      // call a method using this rs.
      processMyResultSet( rs ); // example
    } // if rs is 2
    // ... etc

    // check whether there exist more result sets  
    hasMoreResultSets = stmt.getMoreResults();  
} // while results

Refer to:

Community
  • 1
  • 1
Ravinder Reddy
  • 23,692
  • 6
  • 52
  • 82
-1

No you can't. What are you expecting to get by calling statement.execute(...)? It returns one ResultSet (... which means one table).

You can just call "select fullName from user where user_id in (1, 2)" to geht back both results.

Having semicolons in JDBC statements is very error prone in general. Some JDBC drivers do not support this (e.g. IBM's JDBC driver for DB2 10.x throws an exception if you close your SQL statement with ";").

roehrijn
  • 1,387
  • 1
  • 11
  • 20
  • This is just not true. JDBC can return multiple result sets for one statement / query. You use statement.getResultSet() to get the current result set, statement.next() to move to the next one. You need to set the allowMultiQueries properties to true to disable JDBC safeguards since allowing semicolon opens up SQL injection attack vectors. – flodin Mar 31 '20 at 07:20