Restrictions
Vous pouvez demander le catalogue système pg_database
- accessible depuis n'importe quelle base de données dans le même cluster de bases de données. La partie la plus délicate est qu'elle CREATE DATABASE
ne peut être exécutée que comme une seule instruction. Le manuel:
CREATE DATABASE
ne peut pas être exécuté dans un bloc de transaction.
Il ne peut donc pas être exécuté directement dans une fonction ou une DO
instruction, où il se trouverait implicitement dans un bloc de transaction.
(Les procédures SQL, introduites avec Postgres 11, ne peuvent pas non plus aider .)
Solution de contournement à partir de psql
Vous pouvez le contourner à partir de psql en exécutant l'instruction DDL de manière conditionnelle:
SELECT 'CREATE DATABASE mydb'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec
Le manuel:
\gexec
Envoie le tampon de requête actuel au serveur, puis traite chaque colonne de chaque ligne de la sortie de la requête (le cas échéant) comme une instruction SQL à exécuter.
Solution de contournement depuis le shell
Avec \gexec
vous n'avez besoin d'appeler psql qu'une seule fois :
echo "SELECT 'CREATE DATABASE mydb' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec" | psql
Vous aurez peut-être besoin de plus d'options psql pour votre connexion; rôle, port, mot de passe, ... Voir:
La même chose ne peut pas être appelée psql -c "SELECT ...\gexec"
car il \gexec
s'agit d'une méta-commande psql et l' -c
option attend une seule commande pour laquelle le manuel indique:
command
doit être soit une chaîne de commande entièrement analysable par le serveur (c'est-à-dire qu'elle ne contient aucune fonctionnalité spécifique à psql), soit une seule commande de barre oblique inverse. Ainsi, vous ne pouvez pas mélanger les méta-commandes SQL et psql dans une -c
option.
Solution de contournement depuis la transaction Postgres
Vous pouvez utiliser une dblink
connexion de retour à la base de données actuelle, qui s'exécute en dehors du bloc de transaction. Les effets ne peuvent donc pas non plus être annulés.
Installez le module supplémentaire dblink pour cela (une fois par base de données):
Ensuite:
DO
$do$
BEGIN
IF EXISTS (SELECT FROM pg_database WHERE datname = 'mydb') THEN
RAISE NOTICE 'Database already exists'; -- optional
ELSE
PERFORM dblink_exec('dbname=' || current_database() -- current db
, 'CREATE DATABASE mydb');
END IF;
END
$do$;
Encore une fois, vous aurez peut-être besoin de plus d'options psql pour la connexion. Voir la réponse ajoutée d'Ortwin:
Explication détaillée pour dblink:
Vous pouvez en faire une fonction pour une utilisation répétée.
dblink_connect
.\gexec
lorsque j'ai exécuté la première requête à partir du shell, mais cela a fonctionné.une autre alternative, juste au cas où vous voudriez avoir un script shell qui crée la base de données si elle n'existe pas et la garde autrement telle quelle:
J'ai trouvé cela utile dans les scripts de provisioning devops, que vous voudrez peut-être exécuter plusieurs fois sur la même instance.
la source
c:\Program Files\PostgreSQL\9.6\bin $ psql.exe -U admin -tc "SELECT 1 FROM pg_database WHERE datname = 'my_db'" | grep -q 1 || psql -U admin -c "CREATE DATABASE my_db" 'grep' is not recognized as an internal or external command, operable program or batch file.
Qu'ai-je fait de mal ?grep
sur votre chemin. Sous Windows,grep
n'est pas installé par défaut. Vous pouvez recherchergnu grep windows
une version qui pourrait fonctionner sur Windows.J'ai dû utiliser une version légèrement étendue @Erwin Brandstetter utilisée:
J'ai dû activer l'
dblink
extension, plus j'ai dû fournir les informations d'identification pour dblink. Fonctionne avec Postgres 9.4.la source
Si vous ne vous souciez pas des données, vous pouvez d'abord supprimer la base de données, puis la recréer:
la source
PostgreSQL ne prend pas en charge
IF NOT EXISTS
deCREATE DATABASE
déclaration. Il est pris en charge uniquement dansCREATE SCHEMA
. De plus,CREATE DATABASE
il ne peut pas être émis en transaction, il ne peut donc pas être enDO
bloc avec capture d'exception.Lorsque
CREATE SCHEMA IF NOT EXISTS
est émis et que le schéma existe déjà, une notification (pas d'erreur) avec des informations d'objet en double est générée.Pour résoudre ces problèmes, vous devez utiliser l'
dblink
extension qui ouvre une nouvelle connexion au serveur de base de données et exécute la requête sans entrer dans la transaction. Vous pouvez réutiliser les paramètres de connexion en fournissant une chaîne vide.Vous trouverez ci-dessous du
PL/pgSQL
code qui simule entièrementCREATE DATABASE IF NOT EXISTS
avec le même comportement que dansCREATE SCHEMA IF NOT EXISTS
. Il appelleCREATE DATABASE
viadblink
, catchduplicate_database
exception (qui est émis lorsque la base de données existe déjà) et le convertit en avis avec propagationerrcode
. Le message de chaîne a été ajouté, skipping
de la même manièreCREATE SCHEMA IF NOT EXISTS
.Cette solution est sans condition de concurrence comme dans d'autres réponses, où la base de données peut être créée par un processus externe (ou une autre instance du même script) entre la vérification de l'existence de la base de données et sa propre création.
De plus, en cas d'
CREATE DATABASE
échec avec une autre erreur que la base de données existe déjà, cette erreur est propagée en tant qu'erreur et n'est pas supprimée en silence. Il n'y a qu'un piège pour l'duplicate_database
erreur. Donc, il se comporte vraiment comme il seIF NOT EXISTS
doit.Vous pouvez mettre ce code dans sa propre fonction, l'appeler directement ou à partir d'une transaction. La simple restauration (restaurer la base de données supprimée) ne fonctionnerait pas.
Sortie de test (appelée deux fois via DO puis directement):
la source
Si vous pouvez utiliser shell, essayez
Je pense que
psql -U postgres -c "select 1" -d $DB
c'est plus facileSELECT 1 FROM pg_database WHERE datname = 'my_db'
et n'a besoin que d'un seul type de devis, plus facile à combinersh -c
.J'utilise ceci dans ma tâche ansible
la source
Créez simplement la base de données à l'aide de l'
createdb
outil CLI:Si la base de données existe, elle renverra une erreur:
la source
Mettez à niveau vers PostgreSQL 9.5 ou supérieur. Si (non) existe a été introduit dans la version 9.5.
la source
if not exists
pourCREATE DATABASE
- même pas dans Postgres 11 postgresql.org/docs/current/static/sql-createdatabase.html