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