Проверьте, существует ли база данных в PostgreSQL с помощью оболочки

Мне было интересно, сможет ли кто-нибудь рассказать мне, можно ли использовать оболочку для проверки наличия базы данных PostgreSQL?

Я создаю оболочку script, и я хочу, чтобы она создавала базу данных, если она еще не существует, но до сих пор не смогла увидеть, как ее реализовать.

Ответ 1

Я использую следующую модификацию решения 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

Ответ 2

Мне кажется, что работает следующий код оболочки:

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

Ответ 3

[email protected]:~$ psql -l | grep <exact_dbname> | wc -l

Это вернет 1, если указанная база данных существует или 0 в противном случае.

Кроме того, если вы попытаетесь создать существующую базу данных, postgresql вернет сообщение об ошибке следующего вида:

[email protected]:~$ createdb template1
createdb: database creation failed: ERROR:  database "template1" already exists

Ответ 4

Я новичок в postgresql, но следующая команда - это то, что я использовал для проверки наличия базы данных

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

Ответ 5

Я совмещаю другие ответы с лаконичной и совместимой с POSIX формой:

psql -lqtA | grep -q "^$DB_NAME|"

Возврат true (0) означает, что он существует.

Если вы подозреваете, что имя вашей базы данных может иметь нестандартный символ, например $, вам потребуется немного более длинный подход:

psql -lqtA | cut -d\| -f1 | grep -qxF "$DB_NAME"

Параметры -t и -A гарантируют, что вывод является сырым, а не "табличным" или пропущенным пробелом. Столбцы разделяются символом трубы |, поэтому либо это значение cut, либо grep должно распознать это. Первый столбец содержит имя базы данных.

EDIT: grep с -x, чтобы избежать совпадений с частичным именем.

Ответ 6

#!/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

Вы можете создать базу данных, если она еще не существует, используя этот метод:

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

Ответ 8

Для полноты, другая версия, использующая регулярное выражение, а не строковое резание:

psql -l | grep '^ exact_dbname\b'

Итак, например:

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

Ответ 9

kibibu принятый ответ ошибочен тем, что grep -w будет соответствовать любому имени, содержащему указанный шаблон, в качестве словарного компонента.

то есть. Если вы ищете "foo", тогда "foo-backup" является совпадением.

Ответ Otheus дает некоторые хорошие улучшения, а короткая версия будет работать корректно для большинства случаев, но чем длиннее из двух предложенных вариантов, тем выше аналогичная проблема с соответствующими подстроками.

Чтобы решить эту проблему, мы можем использовать аргумент POSIX -x для соответствия только целым строкам текста.

На основе ответа Otheus новая версия выглядит следующим образом:

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

Что все сказано, я склонен сказать, что Ответ Николя Грили - где вы действительно спрашиваете postgres о конкретной базе данных - это лучший подход для всех.

Ответ 10

Я все еще довольно неопытен в программировании оболочки, поэтому, если это по какой-то причине неправильно, проголосуйте меня, но не будьте слишком встревожены.

Здание из ответа кибибу:

# 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

Ответ 11

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

более короткая версия

Ответ 12

Другие решения (которые являются фантастическими) упускают из виду тот факт, что 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