为 PostgreSQL 模拟 CREATE DATABASE IF NOT EXISTS?
问题:为 PostgreSQL 模拟 CREATE DATABASE IF NOT EXISTS?
我想通过 JDBC 创建一个不存在的数据库。与 MySQL 不同,PostgreSQL 不支持create if not exists语法。实现这一目标的最佳方法是什么?
应用程序不知道数据库是否存在。它应该检查数据库是否存在,应该使用它。所以连接到所需的数据库是有意义的,如果由于数据库不存在而导致连接失败,它应该创建新数据库(通过连接到默认的postgres数据库)。我检查了 Postgres 返回的错误代码,但找不到任何相同的相关代码。
实现此目的的另一种方法是连接到postgres数据库并检查所需的数据库是否存在并采取相应的措施。第二个工作起来有点乏味。
有没有办法在 Postgres 中实现这个功能?
解答
限制
您可以询问系统目录pg_database- 可从同一数据库集群中的任何数据库访问。棘手的部分是CREATE DATABASE只能作为单个语句执行。说明书:
CREATE DATABASE不能在事务块内执行。
所以它不能直接在函数或DO语句中运行,它会隐式地在事务块中运行。随 Postgres 11 引入的 SQL 过程也无法解决这个问题。
psql 内部的解决方法
您可以在 psql 中通过有条件地执行 DDL 语句来解决它:
SELECT 'CREATE DATABASE mydb'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec
说明书:
\gexec
将当前查询缓冲区发送到服务器,然后将查询输出的每一行的每一列(如果有)视为要执行的 SQL 语句。
从 shell 的解决方法
使用\gexec你只需要调用 psql once:
echo "SELECT 'CREATE DATABASE mydb' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec" | psql
您可能需要更多 psql 选项来进行连接;角色,端口,密码,......请参阅:
- 使用 psql 命令运行批处理文件,无需密码
不能用psql -c "SELECT ...\gexec"调用相同的命令,因为\gexec是一个 psql 元命令,并且-c选项需要一个 command ,手册指出:
command必须是服务器完全可解析的命令字符串(即,它不包含特定于 psql 的功能),或者是单个反斜杠命令。因此,您不能在-c选项中混合使用 SQL 和 psql 元命令。
Postgres 事务中的解决方法
您可以使用dblink连接回到当前数据库,该数据库在事务块之外运行。因此,效果也不能回滚。
为此安装附加模块 dblink(每个数据库一次):
- 如何在PostgreSQL中使用(安装)dblink?
然后:
DO
$do$
BEGIN
IF EXISTS (SELECT FROM pg_database WHERE datname = 'mydb') THEN
RAISE NOTICE 'Database already exists'; -- optional
ELSE
PERFORM dblink_exec('dbname=' || current_database() -- current db
, 'CREATE DATABASE mydb');
END IF;
END
$do$;
同样,您可能需要更多 psql 选项来进行连接。请参阅 Ortwin 添加的答案:
- 为 PostgreSQL 模拟 CREATE DATABASE IF NOT EXISTS?
dblink详解:
- 如何在 PostgreSQL 中进行大的非阻塞更新?
您可以将其设为重复使用的功能。
更多推荐
所有评论(0)