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

Posted

技术标签:

【中文标题】如何将数据从一个表复制到另一个表,然后使用 Java 删除第一个表中的数据?【英文标题】:How to copy data from one table to another and then delete that data in first table using 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 数据库。

【问题讨论】:

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

以上是关于如何将数据从一个表复制到另一个表,然后使用 Java 删除第一个表中的数据?的主要内容,如果未能解决你的问题,请参考以下文章

oracle中如何将数据从一个表复制到另一个表(仅复制其中某些字段)

如何使用可重复对象中的嵌套必填字段将数据从一个表复制到另一个表

如何从一个DataTable中复制数据行到另一个DataTable中

如何使用复制命令在 postgres 中将数据从一个表复制到另一个表

如何将一个数据库表数据复制到另一个数据库

如何将一个数据库中的一个表复制到另一个数据库中去