我想通过 JDBC 创建一个不存在的数据库。与 MySQL 不同,PostgreSQL 不支持create if not exists语法。实现这一目标的最佳方法是什么?
create if not exists
应用程序不知道数据库是否存在。它应该检查数据库是否存在,应该使用它。因此,连接到所需的数据库是有意义的,如果由于数据库不存在而导致连接失败,则应创建新数据库(通过连接到默认postgres数据库)。我检查了 Postgres 返回的错误代码,但找不到任何相同的相关代码。
postgres
实现此目的的另一种方法是连接到postgres数据库并检查所需的数据库是否存在并采取相应的措施。第二个工作起来有点乏味。
有没有办法在 Postgres 中实现这个功能?
您可以询问系统目录pg_database- 可从同一数据库集群中的任何数据库访问。棘手的部分是CREATE DATABASE只能作为单个语句执行。手册:
pg_database
CREATE DATABASE
CREATE DATABASE不能在事务块内执行。
所以它不能直接在函数或DO语句中运行,它会隐式在事务块中。随 Postgres 11 引入的 SQL 过程也无济于事。
DO
您可以在 psql 中通过有条件地执行 DDL 语句来解决它:
SELECT 'CREATE DATABASE mydb' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec
手册:
\gexec 将当前查询缓冲区发送到服务器,然后将查询输出(如果有)的每一行的每一列视为要执行的 SQL 语句。
\gexec
将当前查询缓冲区发送到服务器,然后将查询输出(如果有)的每一行的每一列视为要执行的 SQL 语句。
\gexec你只需要调用psql 一次 :
echo "SELECT 'CREATE DATABASE mydb' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec" | psql
psql -c "SELECT ...\gexec"由于\gexec是 psql 元命令,因此不能调用相同的命令,并且该选项需要手动声明-c的单个 命令:
psql -c "SELECT ...\gexec"
-c
command 必须是服务器完全可解析的命令字符串(即,它不包含特定于 psql 的功能),或者是单个反斜杠命令。因此,您不能在一个-c选项中混合使用 SQL 和 psql 元命令。
command
您可以使用dblink返回到当前数据库的连接,该数据库在事务块之外运行。因此,效果也不能回滚。
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$;