模拟CREATE DATABASE如果不存在PostgreSQL?

我想创build一个不存在的数据库通过JDBC。 不像MySQL,PostgreSQL不支持create if not exists语法。 什么是完成这个最好的方法?

应用程序不知道数据库是否存在。 它应该检查,如果数据库存在,应该使用它。 所以连接到所需的数据库是有道理的,如果由于数据库不存在而导致连接失败,它应该创build新的数据库(通过连接到默认的postgres数据库)。 我检查了Postgres返回的错误代码,但是我找不到任何相同的代码。

另一种方法是连接到postgres数据库,并检查是否存在所需的数据库并采取相应的措施。 第二个是有点繁琐的工作。

有什么办法可以在Postgres中实现这个function吗?

你可以问系统目录。 棘手的部分是(正如已经评论的), CREATE DATABASE只能作为单个语句执行。 每个文档:

CREATE DATABASE不能在事务块内部执行。

所以它不能在一个函数或者DO语句中运行,它将隐含在一个事务块中。 这可以通过使用dblink连接回到当前数据库(在事务块之外运行)来绕过。 因此效果也不能回滚。

您需要安装附加模块dblink(每db一次):

  • 如何在PostgreSQL中使用(安装)dblink?

然后:

 DO $do$ BEGIN IF EXISTS (SELECT 1 FROM pg_database WHERE datname = 'mydb') THEN RAISE NOTICE 'Database already exists'; ELSE PERFORM dblink_exec('dbname=' || current_database() -- current db , 'CREATE DATABASE mydb'); END IF; END $do$; 

关于它是如何工作的详细解释:

  • 我如何在PostgreSQL中进行大量的无阻塞更新?

testingPostgres 9.3。 你可以使这个function重复使用。

另一种select,以防万一你想有一个shell脚本创build数据库,如果它不存在,否则保持原样:

 psql -U postgres -tc "SELECT 1 FROM pg_database WHERE datname = 'my_db'" | grep -q 1 || psql -U postgres -c "CREATE DATABASE my_db" 

我发现这在devops供应脚本中很有用,您可能希望在同一个实例上运行多次。

我不得不使用一个稍微扩展的版本@Erwin Brandstetter使用:

 DO $do$ DECLARE _db TEXT := 'some_db'; _user TEXT := 'posrgres'; _password TEXT := 'posrgres'; BEGIN CREATE EXTENSION IF NOT EXISTS dblink; -- enable extension IF EXISTS (SELECT 1 FROM pg_database WHERE datname = _db) THEN RAISE NOTICE 'Database already exists'; ELSE PERFORM dblink_connect('host=localhost user=' || _user || ' password=' || _password || ' dbname=' || current_database()); PERFORM dblink_exec('CREATE DATABASE ' || _db); END IF; END $do$ 

我必须启用dblink扩展,另外我必须提供dblink的凭据。 适用于Postgres 9.4。