英文:
How to copy data from one table to another and then delete that data in first table using Java?
问题
数据库中有两个表,一个是具有列roll_no(主键)、name、grade和DOB的Student表,另一个是具有列roll_no、name、grade和leaving_date的StudentLeft表。
我想从Student表中删除学生的记录,该记录的roll号由用户输入,并将roll号、姓名、年级和离开日期(记录被删除并添加到表中的日期)添加到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);
preparedStatement2.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数据库。
英文:
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.
答案1
得分: 3
你编写的代码可以大大简化:
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 (...)
块内部的代码执行完成后,连接和语句将会关闭。
通过使用 INSERT INTO ... SELECT
语句,可以一次性将数据从 Student
表转移到 StudentLog
表。这个语句不会返回任何结果集:我们只需执行它,行就会被插入。
DELETE
语句类似:它也不返回任何结果集。我在其中添加了关键字 FROM
,更多是出于约定的考虑,正如另一个答案中指出的,FROM
是可选的。
我还将 catch (SQLException e)
块移到了最后:它将处理连接到数据库或执行任一预处理语句时产生的所有 SQLException。
我保留了尝试加载 Oracle 数据库驱动程序类的代码,但在 catch
块中添加了一个 return
语句:如果有异常,驱动程序不在类路径上,连接到数据库肯定会失败,所以我们最好停止执行。然而,对于最近版本的 Oracle 驱动程序,你不需要这个检查。可以尝试一下:看看代码是否可以在没有这个检查的情况下工作,如果可以,就删除它。
英文:
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.
答案2
得分: 2
不应该你的查询是
DELETE FROM Student WHERE roll_no = ?
而不是
DELETE Student WHERE roll_no = ?
英文:
Shouldn't your query be
DELETE FROM Student WHERE roll_no = ?
instead of
DELETE Student WHERE roll_no = ?
答案3
得分: 0
你的删除代码使用了错误的预处理语句,缺少了一个执行操作。
建议按照以下方式使用 try-with-resources 进行编写,以实现自动关闭,即使在返回或异常时也能关闭。(它还会处理变量范围。)
public static void main(String[] args) throws SQLException {
int rollNo = Integer.parseInt(args[0]);
// 可能有更好的语句。
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 { // 检查你是否需要这个。这是为了旧的发现机制。
Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch (ClassNotFoundException e) {
throw new IllegalStateException("未提供数据库驱动程序", 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); // 不是 preparedStatement
preparedStatement2.executeUpdate();
}
connection.commit();
}
}
然后,应该使用一个语句(INSERT SELECT)向数据库中进行SELECT+INSERT操作。
对于 StudentLog 的 SQL 对我来说有点难以理解,但一个很好的 INSERT 语句可以是:
INSERT INTO StudentLog VALUES(roll_no, name, standard)
SELECT roll_no, name, grade
FROM Student
WHERE roll_no = ?
消除了需要在 Java 中嵌套数据库访问的必要性。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论