【问题标题】:Execute multiple SQL statements in java在java中执行多条SQL语句
【发布时间】:2014-06-11 07:38:02
【问题描述】:

我想在 Java 中执行查询。

我创建了一个连接。然后我想执行一个INSERT 语句,完成后,连接关闭,但我想通过连接执行一些插入语句,当循环完成时关闭连接。

我能做什么?

我的示例代码是:

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!");
    }        
}

select语句("SELECT * from test.special_columns")执行时,必须循环两次,但是当(stmt.executeUpdate("" + script))执行完毕,则关闭连接,从类中返回。

【问题讨论】:

  • 你有可能遇到异常吗?
  • 我不这么认为,因为当我打印脚本并为 sqlPlus 执行它们时,它们没问题并且插入成功
  • 在循环中添加一些System.out.println() 语句以查看发生了什么或使用调试器。
  • 我建议将 try/catch 放在你的循环周围 - 并打印你可能遇到的任何异常。可能会有一些你不太期待的事情。

标签: java sql oracle jdbc


【解决方案1】:

以下示例使用addBatch & executeBatch 命令同时执行多个 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());
   }
} 

结果: 上述代码示例将产生以下结果。结果可能会有所不同。

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

来源:Execute multiple SQL statements

【讨论】:

    【解决方案2】:

    在没有架构或每个表中包含的数据的情况下,我将做出以下假设:

    表格special_columns 可能如下所示:

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

    表格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    
    

    alldata 在插入之后应该是这样的:

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

    鉴于这些假设,您可以像这样复制数据:

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

    有几点需要注意:

    • MAX_BATCH_SIZE 应根据您的数据库配置和插入的数据设置为一个值。
    • 此代码使用 Java 7 try-with-resources 功能确保数据库资源在完成后释放。
    • 您无需执行Class.forName,因为service provider 机制已在DriverManager 的JavaDoc 中详细介绍。

    【讨论】:

      【解决方案3】:

      您的代码中有两个问题。首先,您使用相同的 Statement 对象 (stmt) 来执行选择查询和插入。在 JDBC 中,执行一条语句将关闭前一次在同一对象上执行的 ResultSet

      在您的代码中,您循环遍历ResultSet 并为每一行执行插入操作。然而,执行该语句将关闭ResultSet,因此在下一次迭代中,对next() 的调用将在ResultSet 关闭时抛出SQLException

      解决方案是使用两个Statement 对象:一个用于选择,一个用于插入。然而,默认情况下这并不总是有效,因为您在autoCommit 中工作(这是默认设置),并且使用自动提交,任何语句的执行都将提交任何以前的事务(通常也会关闭ResultSet,尽管这可能在数据库和 JDBC 驱动程序之间有所不同)。您要么需要禁用自动提交,要么将结果集创建为可通过提交保留(除非这已经是 JDBC 驱动程序的默认设置)。

      【讨论】:

        猜你喜欢
        • 2014-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-16
        • 2014-10-25
        • 2012-06-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多