使用shell检查PostgreSQL中是否存在数据库
我想知道是否有人能告诉我是否可以使用shell检查PostgreSQL数据库是否存在使用shell检查PostgreSQL中是否存在数据库,postgresql,shell,Postgresql,Shell,我想知道是否有人能告诉我是否可以使用shell检查PostgreSQL数据库是否存在 我正在制作一个shell脚本,我只希望它在数据库不存在的情况下创建数据库,但到目前为止还无法看到如何实现它。我是postgresql新手,但下面的命令是我用来检查数据库是否存在的命令 postgres@desktop:~$ psql -l | grep <exact_dbname> | wc -l if psql ${DB_NAME} -c '\q' 2>&1; then ec
我正在制作一个shell脚本,我只希望它在数据库不存在的情况下创建数据库,但到目前为止还无法看到如何实现它。我是postgresql新手,但下面的命令是我用来检查数据库是否存在的命令
postgres@desktop:~$ psql -l | grep <exact_dbname> | wc -l
if psql ${DB_NAME} -c '\q' 2>&1; then
echo "database ${DB_NAME} exists"
fi
注/更新(2021年):虽然这个答案有效,但从哲学上讲,我同意其他评论,即正确的方法是询问博士后
检查其中包含psql-c
或--command
的其他答案是否更适合您的用例(例如,或
我使用以下对Arturo溶液的修改:
psql-lqt | cut-d\|-f1 | grep-qw
它做什么
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”、“Access”或“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
(失败)。您的shell将把特殊变量$?
设置为最后一个命令的退出状态。您还可以在条件中直接测试状态:
if psql -lqt | cut -d \| -f 1 | grep -qw <db_name>; then
# database exists
# $? is 0
else
# ruh-roh
# $? is 1
fi
如果psql-lqt | cut-d\|-f1 | grep-qw;那么
#数据库存在
#美元是0
其他的
#鲁卢
#美元是1
fi
以下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
我对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
为完整起见,另一个版本使用正则表达式而不是字符串剪切:
psql -l | grep '^ exact_dbname\b'
例如:
if psql -l | grep '^ mydatabase\b' > /dev/null ; then
echo "Database exists already."
exit
fi
我将其他答案组合成简洁且兼容POSIX的形式:
psql -lqtA | grep -q "^$DB_NAME|"
返回true
(0
)表示它存在
如果您怀疑数据库名称可能包含非标准字符,如$
,则需要稍微长一点的方法:
psql -lqtA | cut -d\| -f1 | grep -qxF "$DB_NAME"
-t
和-A
选项确保输出是原始的,而不是“表格”或空格填充的输出。列由管道字符|
分隔,因此剪切
或grep
必须识别这一点。第一列包含数据库名称
编辑:grep with-x以防止部分名称匹配。如果数据库不存在,可以使用以下方法创建数据库:
if [[ -z `psql -Atqc '\list mydatabase' postgres` ]]; then createdb mydatabase; fi
kibibu的缺陷在于grep-w
将匹配任何包含指定模式作为单词组件的名称
i、 e.如果您查找“foo”,则“foo backup”是匹配项
提供了一些很好的改进,短版本在大多数情况下都能正常工作,但提供的两个变体中的长版本在匹配子字符串方面也存在类似的问题
为了解决这个问题,我们可以使用POSIX-x
参数只匹配文本的整行
基于奥修斯的答案,新版本如下:
postgres@desktop:~$ createdb template1
createdb: database creation failed: ERROR: database "template1" already exists
psql-U“$USER”-lqtA | cut-d\|-f1 | grep-qFx“$DBNAME”
话虽如此,我倾向于说——你可以向postgres询问具体的数据库——是最好的方法。
psql-l | awk'{print$1}'| grep-w
较短的版本其他解决方案(非常好)忽略了一个事实,即如果psql无法连接到主机,它可以在超时前等待一分钟或更长时间。因此,我喜欢此解决方案,它将超时设置为3秒:
PGCONNECT_TIMEOUT=3 psql development -h db -U postgres -c ""
这是用于连接到官方Alpine Docker图像上的开发数据库
另外,如果您正在使用Rails,并且想要在数据库不存在的情况下(如启动Docker容器时)设置该数据库,则该方法效果良好,因为迁移是幂等的:
bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:setup
- 一行:
PGPASSWORD=mypassword psql-Upostgres@hostname-h postgres.hostname.com-tAc'select 1'-d dbnae | | echo 0
如果数据库存在,则返回1;如果不存在,则返回0
- 或更具可读性:
触发器除以零如果不存在,则检查返回代码,如下所示:
postgres@desktop:~$ createdb template1
createdb: database creation failed: ERROR: database "template1" already exists
sql=“从pg_数据库中选择1/count(*),其中datname='db_name'”;
error=$(psql-h host-U user-c“$sql”postgres);
如果$error
然后
回声“不存在”;
其他的
回声“存在”;
fi
第一个建议非常危险。精确的
测试会发生什么?唯一的测试方法是尝试连接到它。这个答案不可靠!如果你的搜索词出现在另一列中,它会打印(不会返回!)非零数字。请参阅kibibu的答案以获得更正确的方法。”当一个名为“foobar”的数据库存在时,grep-wfoo“可能会给您带来误报。更不用说它会在psql输出头中找到所有单词
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