Reputation: 33
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.
Upvotes: 1
Views: 713
Reputation: 64959
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.
Upvotes: 3
Reputation: 109547
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.
Upvotes: 0
Reputation: 84
Shouldn't your query be
DELETE FROM Student WHERE roll_no = ?
instead of
DELETE Student WHERE roll_no = ?
Upvotes: 2