在Java中执行多个SQL语句

11

我想在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 * from test.special_columns") 时,必须循环两次,但当执行 (stmt.executeUpdate("" + script)) 完成后,关闭连接并从类中返回。


1
你是否可能遇到了异常? - Jens
我不认为是这样的,因为当我打印脚本并在sqlPlus上执行它们时,它们都是正常的,插入也成功了。 - saeed.sh
在循环中添加一些 System.out.println() 语句以查看发生了什么,或者使用调试器。 - Jens
我建议在循环周围放置try/catch,并打印任何可能出现的异常。可能会有一些意想不到的情况。 - Aleks G
3个回答

8
以下示例使用 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());
   }
} 
结果: 上述代码示例将会生成以下结果。结果可能会有所不同。
rows before batch execution= 6
Batch executed
rows after batch execution= = 9 

来源: 批量执行多个SQL语句


3

假设缺少模式或每个表中包含的数据,我将做出以下假设:

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特性,以确保数据库资源在使用完后得到释放。
  • 自从引入了服务提供者机制,详见DriverManager的JavaDoc,就不再需要执行Class.forName了。

2
你的代码有两个问题。首先,你使用相同的Statement对象(stmt)来执行select查询和insert操作。在JDBC中,执行语句将关闭同一对象上之前执行的ResultSet
在你的代码中,你循环遍历ResultSet并为每一行执行一个insert操作。然而,执行该语句将关闭ResultSet,因此在下一次迭代时,对next()的调用将抛出SQLException异常,因为ResultSet已经关闭。
解决方法是使用两个Statement对象:一个用于select,一个用于insert。然而,这通常不会默认工作,因为你正在使用autoCommit(这是默认设置),并且自动提交会提交任何以前的事务(这通常也会关闭ResultSet,尽管这可能因数据库和JDBC驱动程序而异)。你需要禁用自动提交或将结果集创建为可在提交后保持不变(除非这已经是JDBC驱动程序的默认设置)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接