简体   繁体   中英

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

Two tables are present in the database, one is Student table with columns roll_no(PK), name, grade and DOB, another table StudentLeft with columns roll_no, name, grade and leaving_date.

I want to delete the record of the student from Student table whose roll no is entered by the user, and add the roll no, name, grade and leaving_date (the date when the record is deleted and added to the table) to StudentLeft table.

This is my method.

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

These are the errors.

  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)

I am using oracle 11g express database.

Shouldn't your query be

DELETE FROM Student WHERE roll_no = ?

instead of

DELETE Student WHERE roll_no = ?

The code you've written can be simplified quite a bit:

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

I've used try-with-resources statements, which simplifies the clean-up of connections and prepared statements: the connection and statements will get closed when the code inside the try (...) block finishes executing.

Transferring data from the Student table to the StudentLog table can be done in one go with an INSERT INTO ... SELECT statement. This statement doesn't return any result set: there's nothing to iterate through, we just execute it and the row gets inserted.

The DELETE statement is similar: it too returns no result set. I've added the keyword FROM to it out of convention more than anything else: as pointed out on another answer, FROM is optional.

I've also moved the catch (SQLException e) block to the end: that will handle all SQLExceptions generated when connecting to the database or executing either of the prepared statements.

I've kept the code that attempts to load the Oracle database driver class, but added a return statement in the catch block: if there's an exception, the driver isn't on the classpath and connecting to the database is guaranteed to fail so we may as well stop. However, for recent versions of the Oracle driver you don't need this check. Experiment with it: see if the code works without this check and if so, remove it.

Your DELETE code used the wrong prepared statement, missing an execute.

It is advisable to use try-with-resources as below, for the automatic closing, even on return or exception. (It also takes care of variable scopes.)

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

Then one should SELECT+INSERT to the database, using one statement (INSERT SELECT).

The SQL of the StudentLog is a bit incomprehensible to me, but a nice INSERT would be:

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

Removing the need java nesting of database accesses.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM