如何通过Java代码创建和删除数据库,模式PostgreSQL?

时间:2016-09-16 03:42:00

标签: java postgresql

我试试

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

import com.ibatis.common.jdbc.ScriptRunner;

public static void createDatabase() throws ClassNotFoundException, SQLException {
        Class.forName("org.postgresql.Driver");
        Connection connection = DriverManager.getConnection("jdbc:postgresql://127.0.0.1:5432/postgres", "postgres", "123456a@");
        Statement stmt = connection.createStatement();
        stmt.executeQuery("CREATE DATABASE IF NOT EXISTS foo");
        stmt.executeQuery("USE foo");
        connection.close();
    }

public static void dropDatabase() throws ClassNotFoundException, SQLException {
    Class.forName("org.postgresql.Driver");
    Connection connection = DriverManager.getConnection("jdbc:postgresql://127.0.0.1:5432/", "postgres", "123456a@");
    Statement statement = connection.createStatement();
    statement.executeUpdate("DROP DATABASE foo");
    connection.close();
}

但创建,也丢弃方法不成功。

调用create method时出错:

Exception in thread "main" org.postgresql.util.PSQLException: ERROR: syntax error at or near "NOT"
  Position: 20
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2453)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2153)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:286)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:432)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:358)
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:305)
    at org.postgresql.jdbc.PgStatement.executeCachedSql(PgStatement.java:291)
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:269)
    at org.postgresql.jdbc.PgStatement.executeQuery(PgStatement.java:236)
    at com.nttdata.RunSqlScript.createDatabase(RunSqlScript.java:57)
    at com.nttdata.RunSqlScript.main(RunSqlScript.java:27)

调用drop方法时出错:

Exception in thread "main" org.postgresql.util.PSQLException: ERROR: database "foo" is being accessed by other users
  Detail: There is 1 other session using the database.
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2453)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2153)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:286)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:432)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:358)
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:305)
    at org.postgresql.jdbc.PgStatement.executeCachedSql(PgStatement.java:291)
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:269)
    at org.postgresql.jdbc.PgStatement.executeUpdate(PgStatement.java:249)
    at com.nttdata.RunSqlScript.dropDatabase(RunSqlScript.java:71)
    at com.nttdata.RunSqlScript.main(RunSqlScript.java:28)

2 个答案:

答案 0 :(得分:3)

首先,在您的问题中创建数据库时使用的SQL语法不正确。堆栈跟踪说明了不正确的语法。

如果要检查数据库是否存在,那么您可能需要在Java代码中执行以下操作:

ResultSet rs = stmt.executeQuery("select datname from pg_database where datname like 'foo';");

不是IF NOT EXISTS方法

访问此rs对象将告诉您数据库是否存在。然后,您可以相应地触发CREATEDELETE数据库操作。

String databaseName = "";
if(rs.next()) {
    databaseName = rs.getString("datname");
}
stmt.executeQuery("DROP DATABASE " + databaseName);

如果直接DROP DATABASE不起作用(我曾经多次面对过),您可以考虑使用dropdb实用程序或以下方法之一。

<强> APPROACH-1

使用以下查询来防止将来与您的数据库建立连接:

REVOKE CONNECT ON DATABASE foo FROM public;

然后,您可以终止除此之外的所有与此数据库的连接:

SELECT pid, pg_terminate_backend(pid) 
FROM pg_stat_activity 
WHERE datname = current_database() AND pid <> pg_backend_pid();

由于您已将CONNECT权限撤销到相应的数据库,因此不再有外部auto-connect将无法执行此操作。您现在可以毫无问题地删除数据库。

<强> APPROACH-2:

这种方法采用批处理作业方式,您可以从相应的jar中调用此类:

Process batchProcess = Runtime.getRuntime().exec("C:/Program Files/PostgreSQL/9.5/bin/psql -h \"DB SERVER ADDRESS\" -U postgres -f C:/batch.sql");

batch.sql包含SQL DROP DATABASE语句,在执行时将被删除。

希望这有帮助!

答案 1 :(得分:1)

您可以尝试使用的选项是使用liquibase之类的数据库迁移工具。您可以从liquibase尝试几种选择。一种是从代码直接执行可执行文件(首先使用更改集创建数据库更改日志文件。更改集中的一个命令将是可执行文件

<changeSet author="exec-change-drop" id="drop-foo">
    <executeCommand executable="<bat file with drop for PSQL or dropdb>"/>
</changeSet>

您可以尝试的另一个选项是编写一个sql并调用它

<changeSet id="exec-change-drop2" author="drop-foo-2">  
   <sql>DROP DATABASE foo;</sql>  
</changeSet>

然后,您可以按照以下代码执行此操作

Class.forName("org.postgresql.Driver");
    Connection connection = DriverManager.getConnection("jdbc:postgresql://127.0.0.1:5432/postgres", "postgres", "123456a@");

Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));

Liquibase liquibase = new liquibase.Liquibase("path/to/changelog.xml", new ClassLoaderResourceAccessor(), database);

liquibase.update(new Contexts(), new LabelExpression());

请注意,您的changeLogSchema可能需要位于不同的架构中,以便无缝执行。

另外liquibase可以添加maven(这是应该的方式)并执行