如何通过JDBC截断Postgresql表

5
我有一个Postgresql数据库,希望使用JDBC截断一些表。我该怎么做?
这是我的尝试,但都失败了...甚至连错误提示都没有:
使用CallableStatement。
try (Connection connection = getConnection();
     CallableStatement statement = connection.prepareCall("TRUNCATE " + tableName)) {
  return statement.execute();
}

使用Statement

try (Connection connection = getConnection();
     Statement statement  = connection.createStatement()) {
  return statement.execute("TRUNCATE " + tableName);
}

使用PreparedStatement
try (Connection connection = getConnection();
     PreparedStatement statement = connection.prepareStatement("TRUNCATE " + tableName)) {
  return statement.execute();
}

看起来你的错误在客户端代码中被吞掉了。在finally之前加上catch(Exception e) {e.printStacktrace();}块。你可以通过使用DriverManager.setLogWriter() API启用跟踪,或者参考实际的驱动程序指南。你正在使用哪个JDBC驱动程序? - Bimalesh Jha
不,异常并没有被忽略。我在第二次尝试中更改了代码如下:boolean result = statement.execute("TRUNCATE " + tableName); System.out.println("Everything is ok"); return result;,然后我在控制台上看到了“Everything is ok”。 感谢您提供有关logwriter信息的信息。我正在使用驱动程序org.postgresql:postgresql:9.3-1101-jdbc4(从Maven检索)。 现在你正在关注错误的部分。请不要告诉我我做错了什么,请告诉我如何正确地做,以及您自己如何做。 - Olivier Grégoire
请使用Statement.executeUpdate方法,而不是execute - krokodilko
Statement statement = connection.createStatement(); statement.executeUpdate("TRUNCATE " + tableName); System.out.println("OK")仍然无法正常工作,但仍然打印“OK”。Bimalesh,我知道截断不起作用,因为表中有超过500条记录,而我只插入了100条。如果我正确地截断表格,那么表格应该只有100条记录。就像我在数据库中直接执行时一样。在截断后我需要提交或者做些其他的事情吗? - Olivier Grégoire
你的代码没有 catch 部分,会忽略所有错误,你必须捕获异常并检查错误代码/消息。 - krokodilko
显示剩余6条评论
3个回答

16

截断后,我需要提交:

try (Connection connection = getConnection();
     Statement statement = connection.createStatement()) {
  int result = statement.executeUpdate("TRUNCATE " + tableName);
  connection.commit();
  return result;
}

根据文档

在表数据方面,TRUNCATE与事务安全:如果周围的事务没有提交,则截断将被安全地回滚。


它不应该是 "TRUNCATE TABLE " + tableName 吗? - Marteng
1
@Marteng 不,根据文档 - Olivier Grégoire

4

如果表格存在依赖关系,您可能会遇到问题。如果是这样,请首先截断父表,然后使用CASCADE选项。

Connection connection = getConnection();
try {
    PreparedStatement statement  = connection.prepareStatement("TRUNCATE " + parentTable1, parentTable2, ... + " CASCADE");
    try {
        return statement.execute();
    } finally {
        statement.close();
    }
} finally {
    connection.close();
}

0

首先,如果您正在截断表格,您可能还想同时重新启动IDENTITY(除了可能像John Hogan提到的那样执行CASCADE)。

其次,关于执行connection.commit(),假设您已将autocommit设置为OFF。我的Postgres设置为ON(显然,这有时是默认设置)。 如果它被设置为ON,则调用commit是不必要的,并且会导致错误: “org.postgresql.util.PSQLException:当启用autoCommit时无法提交。”

第三,您可能没有截断表格(或重新启动identity)的权限。在这种情况下,您需要:

DELETE from your_table
SELECT setval('your_table_id', 1)

以下内容对我有效:
public String truncateTable(String tableName, boolean cascadeFlag) {
    String message = "";
    try {
        connection = DriverManager.getConnection(url, username, password);
        Statement statement = connection.createStatement();
        String truncation = "TRUNCATE TABLE yourSchema." + tableName + " RESTART IDENTITY" + (cascadeFlag ? " CASCADE" : "");
        System.out.println("truncateTable: Executing query '" + truncation + "'.");
        int result = statement.executeUpdate(truncation);
        // connection.commit();  // If autocommit is enabled (which it is for our DB), then throws exception after truncating the table.
        statement.close();
        connection.close();
    } catch (SQLException sqlex) {
        message = "Could not truncate table " + tableName + ". " + sqlex.getMessage();
        System.err.println(message);
        sqlex.printStackTrace();
    }
    return message;
}

另外:

public int deleteResetTable(String tableName, String fieldName) {
        int affectedRows = 0;
        try {
            connection = DriverManager.getConnection(url, username, password);
            String sql = "DELETE FROM yourSchema." + tableName;
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            affectedRows = preparedStatement.executeUpdate();
            System.out.println("Deleted " + affectedRows+ " rows from table " + tableName + ".");
            sql = "SELECT setval('yourSchema." + fieldName + "', 1)";
            preparedStatement = connection.prepareStatement(sql);
            affectedRows = preparedStatement.executeUpdate();
            System.out.println("Reset " + affectedRows+ " values from table " + tableName + ".");
        } catch (SQLException ex) {
            System.out.println("Failed to delete rows from " + tableName + " " + ex.getMessage());
        }
        return affectedRows;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接