我想创建一个不通过JDBC存在的数据库.与MySQL不同,PostgreSQL不支持create if not exists语法.实现这一目标的最佳方式是什么?

应用程序不知道数据库是否存在.它应该判断,如果数据库存在,就应该使用它.因此,连接到所需的数据库是有意义的,如果由于数据库不存在而导致连接失败,它应该创建新的数据库(通过连接到默认的postgres数据库).我判断了Postgres返回的错误代码,但找不到任何相同的相关代码.

实现这一点的另一种方法是连接到postgres数据库,判断所需的数据库是否存在,并采取相应的措施.第二个有点乏味.

有没有办法在Postgres中实现这一功能?

推荐答案

限制

您可以询问系统目录pg_database——可从同一数据库群集中的任何数据库访问.棘手的是CREATE DATABASE只能作为一条语句执行.The manual:

CREATE DATABASE不能在事务块内执行.

因此,它不能直接在函数或DO语句中运行,因为它会隐式地在事务块中运行.SQL程序,与Postgres 11、cannot help with this either一起引入.

psql内部的解决方法

您可以通过有条件地执行DDL语句,在psql中解决这个问题:

SELECT 'CREATE DATABASE mydb'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec

The manual:

\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 -c "SELECT ...\gexec"不能调用同样的命令,因为\gexec是一个psql元命令,-c选项需要一个command,其中the manual states:

102必须是完全可由服务器解析的命令字符串(即,它不包含特定于psql的功能),或者是单个反斜杠命令.因此,不能在-c选项中混合使用SQL和psql元命令.

Postgres交易中的解决方案

您可以使用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$;

同样,连接可能需要更多的psql选项.见奥特温补充的答案:

dblink的详细说明:

您可以将其作为一个函数重复使用.

Sql相关问答推荐

基于模式或其他行集的数据复制

将SEMI JOIN、ANTI JOIN转换为非连接SQL

基于列对多行求和的查询

SQL:计算与另一列中给定值互斥的匹配项

在查询Oracle SQL中创建替代ID

使用多个WITH子查询的替代方法

输出连续出现两次以上的行

如何在android房间中进行多个加入

计算不同模式的时间跨度

SQL 查询是否返回列表中仅包含某些值而不包含其他值的行?

如何使用最后一个非 NULL 值在 PostgreSQL 列中填充 NULL 值

复制行并根据 Oracle SQL 中其他表的值更改值

snowflake中的动态文件名生成

在没有订单的情况下,如何生成一个值为0的顾客天数行

从 varchar 列中删除特殊字符后的前面的零和字符时遇到问题

使用其他表 SUM 的交换价格转换价格并获得 AVG

为 sqlite 全文搜索 (fts) 创建触发器时出现虚拟表的不安全使用

如何找到特定时间间隔内的最大和最小日期?

在 Athena / Presto 中提取 JSON 对象以获取动态密钥

在 Microsoft SQL Server 中,如何只为特定值保留不同的行?