我可以用MySQL Connector / J执行多个以分号分隔的查询吗?

我的mysql db的jdbc驱动程序是版本5.1.25。

我想像这样执行sql查询:

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

我总是收到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) 

但是当我从命令行运行同样的查询(以分号分隔)时,它可以正常工作并按预期输出两个表。

使用; 在大多数数据库的查询中不起作用,因为它通常不是语句语法本身的一部分,而是命令行或脚本输入的终止符,用于分隔语句。 命令行或脚本处理器将分号视为语句完成的信号,并可以发送到服务器。

同样在JDBC中,单个语句准备(或执行)应该只是一个实际语句,因此不允许多个语句,因此也不需要使用分号,对于某些(大多数?)数据库,也需要使用分号不是语句语法的一部分,只包含一个语法错误。

如果要执行多个语句,则需要使用单独的执行。 从技术上讲,MySQL确实有一个选项可以支持多个执行,这些执行可以通过连接属性启用。 此行为不符合JDBC规范/ API,并使您的代码不那么可移植。 请参阅Connector / J的驱动程序/数据源类名,URL语法和配置属性上的allowMultiQueries

我想像这样执行sql查询:

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

仅当您设置了一个数据库连接属性以允许一次执行多个查询时,才可以执行此操作。 属性名称为allowMultiQueries=true 。 必须设置此属性并将其与数据库连接请求一起发送到服务器。 一般语法是这样的:

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

这是一些额外的连接属性,如果已经存在的那些,如autoReConnect=true等。

allowMultiQueries属性的可接受值为truefalseyesno 。 使用SQLException在运行时拒绝任何其他值。

您必须使用execute( String sql )或其他变体来获取查询执行的结果。

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

要迭代并处理结果,您需要执行以下步骤:

 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 

参考

  • 在单个语句中用java执行多个查询
    • 关于SO的类似post之一,我给出了答案。

不,你不能。 你期望通过调用statement.execute(…)得到什么? 它返回一个ResultSet(…表示一个表)。

你可以调用“select userName in userinid in(1,2)”来选择两个结果。

在JDBC语句中使用分号通常非常容易出错。 某些JDBC驱动程序不支持此操作(例如,如果使用“;”关闭SQL语句,IBM的DB2 10.x JDBC驱动程序会引发exception)。