使用shell检查PostgreSQL中是否存在数据库

时间:2013-01-27 16:10:19

标签: postgresql shell

我想知道是否有人能告诉我是否可以使用shell来检查PostgreSQL数据库是否存在?

我正在创建一个shell脚本,我只希望它创建数据库(如果它还不存在但是到目前为止还没有看到如何实现它。)

14 个答案:

答案 0 :(得分:164)

我使用Arturo解决方案的以下修改:

psql -lqt | cut -d \| -f 1 | grep -qw <db_name>


它做什么

psql -l输出如下内容:

                                        List of databases
     Name  |   Owner   | Encoding |  Collate   |   Ctype    |   Access privileges   
-----------+-----------+----------+------------+------------+-----------------------
 my_db     | my_user   | UTF8     | en_US.UTF8 | en_US.UTF8 | 
 postgres  | postgres  | LATIN1   | en_US      | en_US      | 
 template0 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
           |           |          |            |            | postgres=CTc/postgres
 template1 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
           |           |          |            |            | postgres=CTc/postgres
(4 rows)

使用朴素方法意味着搜索名为“List”的数据库,“访问”或“行”将成功。因此,我们通过一堆内置命令行工具来管理此输出,以便仅搜索第一列。


-t标记删除页眉和页脚:

 my_db     | my_user   | UTF8     | en_US.UTF8 | en_US.UTF8 | 
 postgres  | postgres  | LATIN1   | en_US      | en_US      | 
 template0 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
           |           |          |            |            | postgres=CTc/postgres
 template1 | postgres  | LATIN1   | en_US      | en_US      | =c/postgres          +
           |           |          |            |            | postgres=CTc/postgres

下一位cut -d \| -f 1将垂直管道|字符(使用反斜杠从shell转义)拆分输出,并选择字段1.这样就离开了:

 my_db             
 postgres          
 template0         

 template1         

grep -w匹配整个单词,因此如果您在此方案中搜索temp,则不匹配。 -q选项会禁止写入屏幕的任何输出,因此如果要在命令提示符下以交互方式运行此输出,可以排除-q,以便立即显示某些内容。

请注意,grep -w匹配字母数字,数字和下划线,这正是postgresql中不带引号的数据库名称中允许的字符集(连字符在不带引号的标识符中不合法)。如果您使用的是其他字符,grep -w将不适合您。


如果数据库存在,整个管道的退出状态将为0(成功),如果不存在,则为1(失败)。 shell会将特殊变量$?设置为最后一个命令的退出状态。您还可以直接在条件中测试状态:

if psql -lqt | cut -d \| -f 1 | grep -qw <db_name>; then
    # database exists
    # $? is 0
else
    # ruh-roh
    # $? is 1
fi

答案 1 :(得分:63)

以下shell代码似乎对我有用:

if [ "$( psql -tAc "SELECT 1 FROM pg_database WHERE datname='DB_NAME'" )" = '1' ]
then
    echo "Database already exists"
else
    echo "Database does not exist"
fi

答案 2 :(得分:25)

postgres@desktop:~$ psql -l | grep <exact_dbname> | wc -l

如果指定的数据库存在,则返回1,否则返回0.

此外,如果您尝试创建已存在的数据库,postgresql将返回如下错误消息:

postgres@desktop:~$ createdb template1
createdb: database creation failed: ERROR:  database "template1" already exists

答案 3 :(得分:19)

我是postgresql的新手,但以下命令是我用来检查数据库是否存在的命令

if psql ${DB_NAME} -c '\q' 2>&1; then
   echo "database ${DB_NAME} exists"
fi

答案 4 :(得分:10)

我将其他答案与简洁和POSIX兼容的形式结合起来:

forfiles /S /P "D:\Data" /M "*.txt" /C "cmd /V:ON /C echo !CD!"

返回psql -lqtA | grep -q "^$DB_NAME|" true)表示它存在。

如果您怀疑数据库名称可能包含0等非标准字符,则需要稍微长一点的方法:

$

psql -lqtA | cut -d\| -f1 | grep -qxF "$DB_NAME" -t选项可确保输出为raw,而不是&#34;表格&#34;或空白填充输出。列由管道符-A分隔,因此|cut必须识别这一点。第一列包含数据库名称。

编辑:grep with -x以防止部分名称匹配。

答案 5 :(得分:8)

您可以使用此方法创建数据库(如果它尚不存在):

if [[ -z `psql -Atqc '\list mydatabase' postgres` ]]; then createdb mydatabase; fi

答案 6 :(得分:5)

#!/bin/sh
DB_NAME=hahahahahahaha
psql -U postgres ${DB_NAME} --command="SELECT version();" >/dev/null 2>&1
RESULT=$?
echo DATABASE=${DB_NAME} RESULT=${RESULT}
#

答案 7 :(得分:3)

为了完整性,使用正则表达式而不是字符串剪切的另一个版本:

psql -l | grep '^ exact_dbname\b'

例如:

if psql -l | grep '^ mydatabase\b' > /dev/null ; then
  echo "Database exists already."
  exit
fi

答案 8 :(得分:2)

kibibu的accepted answer存在缺陷,因为grep -w会将包含指定模式的任何名称与单词组件匹配。

即。如果你寻找“foo”,那么“foo-backup”就是一场比赛。

Otheus's answer提供了一些很好的改进,短版本在大多数情况下都能正常工作,但提供的两个变体中的较长时间在匹配子字符串方面也存在类似的问题。

要解决此问题,我们可以使用POSIX -x参数仅匹配文本的整个行。

基于Otheus的回答,新版本看起来像这样:

psql -U "$USER" -lqtA | cut -d\| -f1 | grep -qFx "$DBNAME"

所有人都说,我倾向于说Nicolas Grilly's answer - 你实际上询问有关特定数据库的帖子 - 是最好的方法。

答案 9 :(得分:0)

我对shell编程仍然缺乏经验,所以如果由于某种原因这确实是错误的,请投票给我,但不要太惊慌。

从kibibu的答案建立:

# If resulting string is not zero-length (not empty) then...
if [[ ! -z `psql -lqt | cut -d \| -f 1 | grep -w $DB_NAME` ]]; then
  echo "Database $DB_NAME exists."
else
  echo "No existing databases are named $DB_NAME."
fi

答案 10 :(得分:0)

psql -l|awk '{print $1}'|grep -w <database>

较短版本

答案 11 :(得分:0)

其他解决方案(非常棒)错过了这样一个事实,即psql可以在超时之前等待一分钟或更长时间,如果它无法连接到主机。所以,我喜欢这个解决方案,它将超时设置为3秒:

PGCONNECT_TIMEOUT=3 psql development -h db -U postgres -c ""

这是用于连接官方postgres Alpine Docker映像上的开发数据库。

另外,如果您正在使用Rails并且想要设置数据库(如果它已经存在(如启动Docker容器时)),这很有效,因为迁移是幂等的:

bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:setup

答案 12 :(得分:0)

  • 一行:

PGPASSWORD=mypassword psql -U postgres@hostname -h postgres.hostname.com -tAc 'select 1' -d dbnae || echo 0

如果db存在,则返回1,否则返回0。

  • 或更易读:
if [ "$(PGPASSWORD=mypassword psql -U postgres@hostname -h postgres.hostname.com -tAc 'select 1' -d dbnae || echo 0 )" = '1' ]
then
    echo "Database already exists"
else
    echo "Database does not exist"
fi

答案 13 :(得分:0)

如果触发器不存在,则将其除以零,然后检查返回代码,如下所示:

sql="SELECT 1/count(*) FROM pg_database WHERE datname='db_name'";
error=$(psql -h host -U user -c "$sql" postgres);
if $error
then
  echo "doesn't exist";
else
  echo "exists";
fi