Vérifier si la base de données existe dans PostgreSQL en utilisant shell

je me demandais si quelqu'un pourrait me dire s'il est possible d'utiliser shell pour vérifier si une base de données PostgreSQL existe?

je suis en train de faire un script shell et je veux qu'il crée la base de données seulement s'il n'existe pas déjà mais jusqu'à présent je n'ai pas été capable de voir comment l'implémenter.

96
demandé sur wonea 2013-01-27 20:10:18

12 réponses

j'utilise la modification suivante de la solution D'Arturo:

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


Ce qu'il fait

psql -l produit quelque chose comme:

                                        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)

L'utilisation de l'approche naïve signifie que la recherche d'une base de données appelée "List", "Access" ou "rows" réussira. Donc, nous acheminons cette sortie à travers un tas d'outils de ligne de commande intégrés pour recherche dans la première colonne.


le drapeau -t enlève les en-têtes et les pieds de page:

 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

le bit suivant, cut -d \| -f 1 divise la sortie par le caractère de tube vertical | (échappée de la coque avec un antislash), et sélectionne le champ 1. Il reste:

 my_db             
 postgres          
 template0         

 template1         

grep -w correspond à des mots entiers, et donc ne sera pas correspondez si vous cherchez temp dans ce scénario. L'option -q supprime toute sortie écrite à l'écran, donc si vous voulez exécuter ceci de manière interactive à une invite de commande vous pouvez exclure le -q pour que quelque chose s'affiche immédiatement.

notez que grep -w correspond à des caractères alphanumériques, des chiffres et des underscores, ce qui est exactement l'ensemble de caractères permis dans les noms de base de données non référencés dans postgresql (les traits d'Union ne sont pas légaux dans identificateurs non cotées). Si vous utilisez d'autres caractères, grep -w ne fonctionnera pas pour vous.


l'état de sortie de l'ensemble de ce pipeline sera 0 (succès) si la base de données existe ou 1 (échec) si elle n'existe pas. Votre shell définira la variable spéciale $? au statut de sortie de la dernière commande. Vous pouvez également tester le statut directement dans un conditionnel:

if psql -lqt | cut -d \| -f 1 | grep -qw <db_name>; then
    # database exists
    # $? is 0
else
    # ruh-roh
    # $? is 1
fi
150
répondu kibibu 2016-05-19 07:05:21

le code shell suivant semble fonctionner pour moi:

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
51
répondu Nathan Osman 2016-10-21 14:01:45
postgres@desktop:~$ psql -l | grep <exact_dbname> | wc -l

cela retournera 1 si la base de données spécifiée existe ou 0 autrement.

en outre, si vous essayez de créer une base de données qui existe déjà, postgresql retournera un message d'erreur comme ceci:

postgres@desktop:~$ createdb template1
createdb: database creation failed: ERROR:  database "template1" already exists
23
répondu Arturo 2017-02-27 11:19:08

je suis nouveau à postgresql, mais la commande suivante est ce que j'ai utilisé pour vérifier si une base de données existe

if psql ${DB_NAME} -c '\q' 2>&1; then
   echo "database ${DB_NAME} exists"
fi
18
répondu bruce 2013-03-21 02:05:19

je suis combinant les autres réponses succinctes et compatible POSIX:

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

Un retour de true ( 0 ) signifie qu'il existe.

si vous soupçonnez que votre nom de base de données pourrait avoir un caractère non standard tel que $ , vous avez besoin d'une approche un peu plus longue:

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

les options -t et -A assurent que la sortie est brute et non "tabulaire" ou blanc, collier de sortie. Les colonnes sont séparées par le caractère de pipe | , donc soit le cut ou le grep doit reconnaître ceci. La première colonne contient le nom de base de données.

EDIT: grep-x afin d'empêcher une partie de ce nom correspond.

10
répondu Otheus 2016-05-24 15:58:47
#!/bin/sh
DB_NAME=hahahahahahaha
psql -U postgres ${DB_NAME} --command="SELECT version();" >/dev/null 2>&1
RESULT=$?
echo DATABASE=${DB_NAME} RESULT=${RESULT}
#
5
répondu wildplasser 2013-01-27 16:18:14

vous pouvez créer une base de données, si elle n'existe pas déjà, en utilisant cette méthode:

if [[ -z `psql -Atqc '\list mydatabase' postgres` ]]; then createdb mydatabase; fi
5
répondu Nicolas Grilly 2015-12-09 09:12:30

Par souci d'exhaustivité, une autre version en utilisant les regex plutôt que de la chaîne de coupe:

psql -l | grep '^ exact_dbname\b'

ainsi par exemple:

if psql -l | grep '^ mydatabase\b' > /dev/null ; then
  echo "Database exists already."
  exit
fi
3
répondu Steve Bennett 2014-02-13 12:18:45

kibibu accepté de répondre est erronée en ce qu' grep -w correspond à la tout nom contenant le motif spécifié comme un élément verbal.

c'est à dire Si vous recherchez "foo", puis "foo-backup" est un match.

la réponse D'Otheus offre quelques bonnes améliorations, et la version courte fonctionnera correctement dans la plupart des cas, mais la plus longue des deux variantes offertes présente une problème similaire avec les substrats correspondants.

pour résoudre ce problème, nous pouvons utiliser L'argument POSIX -x pour correspondre seulement entier lignes du texte.

S'appuyant sur la réponse D'Otheus, la nouvelle version ressemble à ceci:

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

que tout dit, je suis enclin à dire que réponse de Nicolas Grilly -- où vous demandez réellement postgres au sujet de la base de données spécifique -- est le meilleure approche de tous.

2
répondu phils 2017-05-23 10:31:29

je suis encore assez inexpérimenté avec la programmation shell, donc si c'est vraiment mal pour une raison quelconque, rejetez-moi, mais ne soyez pas trop alarmé.

bâtiment de la réponse de 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
0
répondu David Winiecki 2013-10-16 09:30:12

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

version plus courte

0
répondu Justin 2016-11-08 10:23:30

les autres solutions (qui sont fantastiques) passent à côté du fait que psql peut attendre une minute ou plus avant de chronométrer si elle ne peut pas se connecter à un hôte. Ainsi, j'aime cette solution, qui fixe le délai d'attente à 3 secondes:

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

ceci est pour se connecter à une base de données de développement sur l'image officielle postgres Alpine Docker.

séparément, si vous utilisez des Rails et que vous voulez configurer une base de données si elle n'existe pas déjà (comme lors du lancement d'un conteneur Docker), cela fonctionne bien, car les migrations sont idempotent:

bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:setup
0
répondu dankohn 2017-06-27 05:10:53