【问题标题】:How to copy data from one table to another and then delete that data in first table using Java?如何将数据从一个表复制到另一个表,然后使用 Java 删除第一个表中的数据?
【发布时间】:2020-12-29 18:31:21
【问题描述】:

数据库中有两张表,一张是 Student 表,列有 roll_no(PK)、name、grade 和 DOB,另一张表 StudentLeft,列有 roll_no、name、grade 和 leave_date。

我想从学生表中删除用户输入卷号的学生的记录,并将卷号,姓名,年级和离开日期(删除记录并添加到表中的日期)添加到StudentLeft 表。

这是我的方法。

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 数据库。

【问题讨论】:

  • 好的......你的代码中有什么(不)工作?您能具体说明您的问题是什么吗?
  • 无法正确理解错误是什么。在执行批处理中显示两个错误,另一个在我关闭准备好的语句的区域中显示。
  • 编辑你的问题并写下这些错误
  • 并且您希望我们知道错误是什么,而您没有向我们显示任何可能出错的信息,更不用说错误消息了?您正在打印您的堆栈跟踪(就我个人而言,我会将它们放在日志文件中),因此您应该确切知道出了什么问题

标签: java database jdbc oracle11g


【解决方案1】:

你写的代码可以简化不少:

  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 语句,它简化了连接和预处理语句的清理:当try (...) 块内的代码完成执行时,连接和语句将关闭。

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

DELETE 语句类似:它也没有返回结果集。我已经将关键字 FROM 添加到其中,而不是其他任何东西:正如在另一个答案中指出的那样,FROM 是可选的。

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

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

【讨论】:

    【解决方案2】:

    你的查询不应该是

    DELETE FROM Student WHERE roll_no = ?
    

    而不是

    DELETE Student WHERE roll_no = ?
    

    【讨论】:

    • 您可以编辑它以提高可读性吗?将你的 sql 插入代码括号
    • 虽然这应该重新措辞,但这可能是 OP 正在寻找的解决方案,所以我不知道为什么有人会否决
    • 如果查询错误,执行将失败。我认为这就是解决方案。
    • 我确实错误地投了反对票,因为我确实以相反的方式阅读了它。抱歉,我已经更改投票了
    【解决方案3】:

    您的 DELETE 代码使用了错误的预处理语句,缺少执行。

    建议使用如下 try-with-resources 来自动关闭, 即使是退货或例外。 (它还负责变量范围。)

    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 嵌套。

    【讨论】:

    • 你错过了DELETE中的错误,应该是DELETE FROM,而不是DELETE
    • @Stultuske 我添加了一个 FROM,docs 告诉 FROM 是可选的。有了 FROM 就没有那么可怕了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-02
    • 2023-03-16
    • 1970-01-01
    相关资源
    最近更新 更多