简体   繁体   English

在java中执行多个SQL语句

[英]Execute multiple SQL statements in java

I want to execute a query in Java . 我想用Java执行查询。

I create a connection. 我创建了一个连接。 Then I want to execute an INSERT statement, when done, the connection is closed but I want to execute some insert statement by a connection and when the loop is finished then closing connection. 然后我想执行一个INSERT语句,完成后,连接关闭,但我想通过连接执行一些insert语句,当循环完成然后关闭连接。

What can I do ? 我能做什么 ?

My sample code is : 我的示例代码是:

public NewClass() throws SQLException {
    try {
        Class.forName("oracle.jdbc.driver.OracleDriver");
    } catch (ClassNotFoundException e) {
        System.out.println("Where is your Oracle JDBC Driver?");
        return;
    }
    System.out.println("Oracle JDBC Driver Registered!");

    Connection connection = null;
    try {
        connection = DriverManager.getConnection(
                "jdbc:oracle:thin:@localhost:1521:orcl1", "test",
                "oracle");
    } catch (SQLException e) {
        System.out.println("Connection Failed! Check output console");
        return;
    }

    if (connection != null) {
        Statement stmt = connection.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT * from test.special_columns");
        while (rs.next()) {
            this.ColName = rs.getNString("column_name");
            this.script = "insert into test.alldata (colname) ( select " +  ColName + "   from test.alldata2       ) " ;
            stmt.executeUpdate("" + script);
        }        
    }
    else {
        System.out.println("Failed to make connection!");
    }        
}

When the select statement ( "SELECT * from test.special_columns" ) is executed, the loop must be twice, but when ( stmt.executeUpdate("" + script) ) is executed and done, then closing the connection and return from the class. 当执行select语句( "SELECT * from test.special_columns" )时,循环必须是两次,但是当执行并完成( stmt.executeUpdate("" + script) ),然后关闭连接并从类返回。

Following example uses addBatch & executeBatch commands to execute multiple SQL commands simultaneously. 以下示例使用addBatchexecuteBatch命令同时执行多个SQL命令。

import java.sql.*;

public class jdbcConn {
   public static void main(String[] args) throws Exception{
      Class.forName("org.apache.derby.jdbc.ClientDriver");
      Connection con = DriverManager.getConnection
      ("jdbc:derby://localhost:1527/testDb","name","pass");
      Statement stmt = con.createStatement
      (ResultSet.TYPE_SCROLL_SENSITIVE,
      ResultSet.CONCUR_UPDATABLE);
      String insertEmp1 = "insert into emp values
      (10,'jay','trainee')";
      String insertEmp2 = "insert into emp values
      (11,'jayes','trainee')";
      String insertEmp3 = "insert into emp values
      (12,'shail','trainee')";
      con.setAutoCommit(false);
      stmt.addBatch(insertEmp1);
      stmt.addBatch(insertEmp2);
      stmt.addBatch(insertEmp3);
      ResultSet rs = stmt.executeQuery("select * from emp");
      rs.last();
      System.out.println("rows before batch execution= "
      + rs.getRow());
      stmt.executeBatch();
      con.commit();
      System.out.println("Batch executed");
      rs = stmt.executeQuery("select * from emp");
      rs.last();
      System.out.println("rows after batch execution= "
      + rs.getRow());
   }
} 

Result: The above code sample will produce the following result.The result may vary. 结果:上面的代码示例将产生以下结果。结果可能会有所不同。

rows before batch execution= 6
Batch executed
rows after batch execution= = 9 

Source: Execute multiple SQL statements 来源: 执行多个SQL语句

In the abscence of the schema or the data contained in each table I'm going to make the following assumptions: 在模式的绝对或每个表中包含的数据中,我将做出以下假设:

The table special_columns could look like this: special_columns可能如下所示:

column_name
-----------
column_1
column_2
column_3

The table alldata2 could look like this: alldata2可能如下所示:

column_1  | column_2  | column_3
---------------------------------
value_1_1 | value_2_1 | value_3_1
value_1_2 | value_2_2 | value_3_2    

The table alldata should, after inserts have, happened look like this: 在插入之后,表alldata应该发生如下:

colname
---------
value_1_1
value_1_2
value_2_1
value_2_2
value_3_1
value_3_2

Given these assumptions you can copy the data like this: 根据这些假设,您可以复制数据,如下所示:

try (
  Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl1", "test", "oracle")
)
{
  StringBuilder columnNames = new StringBuilder();

  try (
    Statement select = connection.createStatement();
    ResultSet specialColumns = select.executeQuery("SELECT column_name FROM special_columns");
    Statement insert = connection.createStatement()
  )
  {
    while (specialColumns.next())
    {
      int batchSize = 0;             

      insert.addBatch("INSERT INTO alldata(colname) SELECT " + specialColumns.getString(1) + " FROM alldata2"); 

      if (batchSize >= MAX_BATCH_SIZE)
      { 
        insert.executeBatch();
        batchSize = 0;
      }
    }

    insert.executeBatch();
  }

A couple of things to note: 有几点需要注意:

  • MAX_BATCH_SIZE should be set to a value based on your database configuration and the data being inserted. 应根据数据库配置和插入的数据将MAX_BATCH_SIZE设置为一个值。
  • this code is using the Java 7 try-with-resources feature to ensure the database resources are released when they're finished with. 此代码使用Java 7 try-with-resources功能来确保数据库资源在完成后发布。
  • you haven't needed to do a Class.forName since the service provider mechanism was introduced as detailed in the JavaDoc for DriverManager . 您不需要执行Class.forName因为服务提供程序机制是在JavaDoc for DriverManager中详细介绍的。

There are two problems in your code. 您的代码中存在两个问题。 First you use the same Statement object ( stmt ) to execute the select query, and the insert. 首先,使用相同的Statement对象( stmt )来执行select查询和插入。 In JDBC, executing a statement will close the ResultSet of the previous execute on the same object. 在JDBC中,执行语句将关闭同一对象上一次执行的ResultSet

In your code, you loop over the ResultSet and execute an insert for each row. 在代码中,循环遍历ResultSet并为每一行执行插入。 However executing that statement will close the ResultSet and therefor on the next iteration the call to next() will throw an SQLException as the ResultSet is closed. 但是,执行该语句将关闭ResultSet ,因此在下一次迭代时,对next()的调用将在ResultSet关闭时抛出SQLException

The solution is to use two Statement objects: one for the select and one for the insert. 解决方案是使用两个Statement对象:一个用于select,一个用于insert。 This will however not always work by default, as you are working in autoCommit (this is the default), and with auto commit, the execution of any statement will commit any previous transactions (which usually also closes the ResultSet , although this may differ between databases and JDBC drivers). 但是,默认情况下这并不总是有效,因为您正在使用autoCommit (这是默认设置),并且使用自动提交,任何语句的执行都将提交任何先前的事务(通常也会关闭ResultSet ,尽管这可能会有所不同)数据库和JDBC驱动程序)。 You either need to disable auto commit, or create the result set as holdable over commit (unless that already is the default of your JDBC driver). 您需要禁用自动提交,或者将结果集创建为可保持提交(除非已经是JDBC驱动程序的默认设置)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM