Answers:
我对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)
使用幼稚的方法意味着将成功搜索名为“列表,访问”或“行”的数据库,因此我们通过一系列内置命令行工具将此输出通过管道传输,仅在第一列中进行搜索。
该-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
用垂直竖线|
字符(用反斜杠从外壳转义)分隔输出,并选择字段1。这将留下:
my_db
postgres
template0
template1
grep -w
匹配整个单词,因此如果您temp
在这种情况下进行搜索,则不会匹配。该-q
选项禁止显示任何写入屏幕的输出,因此,如果要在命令提示符下以交互方式运行此输出,则可能要排除-q
这样的内容,以便立即显示某些内容。
请注意,它们grep -w
匹配字母数字,数字和下划线,这恰好是postgresql中未引用数据库名称中允许的字符集(在未引用标识符中连字符是合法的)。如果您使用其他字符,grep -w
将无法使用。
0
如果数据库存在,则整个管道的退出状态将为(成功),否则为1
(失败)。您的外壳程序会将特殊变量设置$?
为最后一个命令的退出状态。您还可以直接在条件中测试状态:
if psql -lqt | cut -d \| -f 1 | grep -qw <db_name>; then
# database exists
# $? is 0
else
# ruh-roh
# $? is 1
fi
wc
完全删除。看到我的修订。(如果你想扭转退出状态,猛砸支持一声巨响运营商:! psql ...
)
wc
命令的建议外,我将使用grep -qw <term>
。0
如果存在匹配项,1
否则将导致外壳返回。然后,$?
将包含返回值,您可以使用该值来确定下一步要执行的操作。因此,我建议wc
在这种情况下不要使用。grep
会做你需要的。
以下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
psql -U user -tAc "SELECT 1 FROM pg_database WHERE datname='DB_NAME'" template1
if [[ $(...) == 1* ]]
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
exact_dbname_test
?测试的唯一方法是尝试连接到它。
psql -l | grep doesnt_matter_what_you_grep | wc -l && echo "true"
vspsql -l | grep it_does_matter_here && echo "only true if grep returns anything"
psql -l | grep '^ exact_dbname\b'
,如果未找到,它将设置退出代码。
我是Postgresql的新手,但是下面的命令是我用来检查数据库是否存在的命令
if psql ${DB_NAME} -c '\q' 2>&1; then
echo "database ${DB_NAME} exists"
fi
psql ${DB_NAME} -c ''
。
您可以使用以下方法创建数据库(如果尚不存在):
if [[ -z `psql -Atqc '\list mydatabase' postgres` ]]; then createdb mydatabase; fi
#!/bin/sh
DB_NAME=hahahahahahaha
psql -U postgres ${DB_NAME} --command="SELECT version();" >/dev/null 2>&1
RESULT=$?
echo DATABASE=${DB_NAME} RESULT=${RESULT}
#
为了完整性,使用正则表达式而不是字符串切割的另一个版本:
psql -l | grep '^ exact_dbname\b'
因此,例如:
if psql -l | grep '^ mydatabase\b' > /dev/null ; then
echo "Database exists already."
exit
fi
\b
与所有答案都存在相同的问题,grep -w
即数据库名称可以包含非单词组成的字符,例如-
,因此匹配尝试foo
也将匹配foo-bar
。
kibibu 接受的答案有缺陷,因为它grep -w
会匹配包含指定模式作为单词组成部分的任何名称。
即,如果您查找“ foo”,则“ foo-backup”是匹配项。
奥修斯的答案提供了一些良好的改进,并且简短的版本在大多数情况下都能正常工作,但是提供的两个变体中的较长者在匹配子字符串方面也存在类似的问题。
要解决此问题,我们可以使用POSIX -x
参数仅匹配文本的整行。
以Otheus的答案为基础,新版本如下所示:
psql -U "$USER" -lqtA | cut -d\| -f1 | grep -qFx "$DBNAME"
综上所述,我倾向于说Nicolas Grilly的答案(您实际上在向postgres查询特定数据库)是所有方法中最好的。
其他解决方案(非常棒)缺少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
... | grep 0
如果数据库不存在,您还可以添加使shell返回值为0,如果不存在,则为1;或... | grep 1
针对相反的行为