如何将数据从一个 table 复制到另一个,然后使用 Java 删除第一个 table 中的数据?

How to copy data from one table to another and then delete that data in first table using Java?

两个 table 存在于数据库中,一个是 Student table,包含列 roll_no(PK)、姓名、年级和 DOB,另一个 table StudentLeft包含 roll_no、姓名、等级和 leaving_date.

我想删除用户输入学号的学生table的学生记录,并添加学号、姓名、年级和leaving_date(入学日期)记录被删除并添加到 table) 到 StudentLeft table.

这是我的方法。

public static void main(String[] args) throws SQLException {
    Connection connection = null;
    PreparedStatement preparedStatement = null, preparedStatement1 = null, preparedStatement2 = null;
    ResultSet resultSet = null;
    String selectQuery = "", updateQuery = "", deleteQuery = "";

    try {
        Class.forName("oracle.jdbc.driver.OracleDriver");
        connection = dataSource.getConnection();
    }
    catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    catch (SQLException e) {
        e.printStackTrace();
    }

    int rollNo = Integer.parseInt(args[0]);

    try {
        selectQuery = "SELECT name, grade FROM Student WHERE roll_no = ?";
        updateQuery = "INSERT INTO StudentLog values WHERE roll_no = ?, name = ?, standard = ?";
        deleteQuery = "DELETE Student WHERE roll_no = ?";
        
        connection.setAutoCommit(false);
        preparedStatement = connection.prepareStatement(selectQuery);
        preparedStatement.setInt(1, rollNo);
        resultSet = preparedStatement.executeQuery();
        preparedStatement1 = connection.prepareStatement(updateQuery);
        preparedStatement1.setInt(1, rollNo);
        
        while (resultSet.next()) {
            String name = resultSet.getString("name");
            String grade = resultSet.getString("grade");
            preparedStatement1.setString(2, name);
            preparedStatement1.setString(3, grade);
            preparedStatement1.addBatch();
        }
        preparedStatement1.executeBatch();
        preparedStatement2 = connection.prepareStatement(deleteQuery);
        preparedStatement.setInt(1, rollNo);
        connection.commit();
    }

    catch (SQLException e) {
        e.printStackTrace();
    }

    try {
        if (!preparedStatement.isClosed() || !preparedStatement1.isClosed() || !preparedStatement2.isClosed()) {
            preparedStatement.close();
            preparedStatement1.close();
            preparedStatement2.close();
        }

        if (!connection.isClosed())
            connection.close();
    }
    
    catch (SQLException e) {
        e.printStackTrace();
    }
}

这些是错误。

  java.sql.BatchUpdateException: ORA-00936: missing expression
    at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10500)
    at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:230)    
    at Q3.main(Q3.java:48)
  Exception in thread "main" java.lang.NullPointerException
    at Q3.main(Q3.java:62)

我正在使用 oracle 11g Express 数据库。

你的查询不应该是

DELETE FROM Student WHERE roll_no = ?

而不是

DELETE Student WHERE roll_no = ?

您的 DELETE 代码使用了错误的准备语句,缺少执行。

建议使用try-with-resources如下,为了自动关闭, 即使在 return 或例外情况下。 (它还负责变量范围。)

public static void main(String[] args) throws SQLException {
    int rollNo = Integer.parseInt(args[0]);

    // Better statements possible.
    final String selectQuery = "SELECT name, grade FROM Student WHERE roll_no = ?";
    final String updateQuery =
        "INSERT INTO StudentLog VALUES WHERE roll_no = ?, name = ?, standard = ?";
    final String deleteQuery = "DELETE FROM Student WHERE roll_no = ?";

    try { // Check whether you need this. It is for the old discovery mechanism.
        Class.forName("oracle.jdbc.driver.OracleDriver");
    }
    catch (ClassNotFoundException e) {
        throw new IllegalStateException("Database driver not provided", e);
    }

    try (Connection connection = dataSource.getConnection()) {
        connection.setAutoCommit(false);
        
        try (PreparedStatement preparedStatement =
                connection.prepareStatement(selectQuery)) {
            preparedStatement.setInt(1, rollNo);
            try (ResultSet resultSet = preparedStatement.executeQuery()) {
                try (PreparedStatement preparedStatement1 =
                        connection.prepareStatement(updateQuery)) {
                    preparedStatement1.setInt(1, rollNo);

                    while (resultSet.next()) {
                        String name = resultSet.getString("name");
                        String grade = resultSet.getString("grade");
                        preparedStatement1.setString(2, name);
                        preparedStatement1.setString(3, grade);
                        preparedStatement1.addBatch();
                    }
                    preparedStatement1.executeBatch();
                }
            }
        }
        try (PreparedStatement preparedStatement2 =
                connection.prepareStatement(deleteQuery)) {
            preparedStatement2.setInt(1, rollNo); // NOT preparedStatement
            preparedStatement2.executeUpdate();
        }
        connection.commit();
    }
}

然后应该 SELECT+INSERT 到数据库,使用一条语句 (INSERT SELECT)。

StudentLog 的 SQL 对我来说有点难以理解,但是一个不错的 INSERT 应该是:

INSERT INTO StudentLog VALUES(roll_no, name, standard)
SELECT roll_no, name, grade
FROM Student
WHERE roll_no = ?

删除 java 嵌套数据库访问的需要。

您编写的代码可以大大简化:

  public static void main(String[] args) {
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
            return;
        }

        int rollNo = Integer.parseInt(args[0]);
        try (Connection connection = dataSource.getConnection()) {
            connection.setAutoCommit(false);

            String transferStatement = "INSERT INTO StudentLog (roll_no, name, standard, leaving_date) " +
                    "SELECT roll_no, name, standard, SYSDATE FROM Student WHERE roll_no = ?";
            try (PreparedStatement stmt = connection.prepareStatement(transferStatement)) {
                stmt.setInt(1, rollNo);
                stmt.executeUpdate();
            }

            String deleteStatement = "DELETE FROM Student WHERE roll_no = ?";
            try (PreparedStatement stmt = connection.prepareStatement(deleteStatement)) {
                stmt.setInt(1, rollNo);
                stmt.executeUpdate();
            }

            connection.commit();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
    }

我使用了 try-with-resources 语句,它简化了连接和准备语句的 clean-up:连接和语句将在 try (...) 块中的代码执行完成时关闭.

将数据从 Student table 传输到 StudentLog table 可以通过 INSERT INTO ... SELECT 语句一次性完成。该语句不 return 任何结果集:没有什么可迭代的,我们只是执行它并插入行。

DELETE 语句类似:它也return 没有结果集。我在其中添加关键字 FROM 比其他任何事情都更符合惯例:正如另一个答案所指出的, FROM 是可选的。

我还将 catch (SQLException e) 块移到了末尾:它将处理连接到数据库或执行任一准备好的语句时生成的所有 SQLExceptions。

我保留了尝试加载 Oracle 数据库驱动程序的代码 class,但在 catch 块中添加了一条 return 语句:如果出现异常,驱动程序不在 class 路径上并且连接到数据库肯定会失败,所以我们不妨停止。但是,对于最新版本的 Oracle 驱动程序,您不需要此检查。试验一下:查看代码是否可以在没有此检查的情况下工作,如果可以,请将其删除。