Créer PostgreSQL RÔLE utilisateur (nom d'utilisateur) si elle n'existe pas
Comment puis-je écrire un script SQL pour créer un RÔLE dans PostgreSQL 9.1, mais sans lever une erreur si elle existe déjà?
Le script courant, tout simplement:
CREATE ROLE my_user LOGIN PASSWORD 'my_password';
Cela échoue si l'utilisateur existe déjà. J'aimerais quelque chose comme:
IF NOT EXISTS (SELECT * FROM pg_user WHERE username = 'my_user')
BEGIN
CREATE ROLE my_user LOGIN PASSWORD 'my_password';
END;
... mais qui ne fonctionne pas - IF
ne semble pas être pris en charge dans la plaine SQL.
J'ai un fichier de commandes qui crée une base de données PostgreSQL 9.1, le rôle et quelques autres choses. Il appelle psql.exe en passant le nom d'un script SQL à exécuter. Jusqu'à présent, tous ces scripts sont plaine SQL et j'aimerais éviter de PL/pgSQL et, si possible.
Vous devez vous connecter pour publier un commentaire.
Simplifier d'une manière similaire à ce que vous aviez à l'esprit:
(Sur @a_horse_with_no_name's réponse et amélioré après @Gregory commentaire.)
À la différence, par exemple, avec
CREATE TABLE
il n'y a pas deIF NOT EXISTS
clause deCRÉER un RÔLE
(encore). Et vous ne peut pas exécuter dynamique des instructions DDL en plaine SQL.Votre demande "d'éviter PL/pgSQL" est impossible, sauf par un autre PL. Le
NE
déclaration utilise plpgsql en tant que par défaut langue de la procédure. La syntaxe permet d'omettre la déclaration explicite:syntax error at or near "$"
quelqu'un A déjà vu ça? L'exécution de v9.5.2. Merci!$
a une signification spéciale dans votre client vous avez besoin pour échapper à la selon les règles de syntaxe de votre client. Essayer de s'échapper$
avec\$
dans le shell Linux. Ou de démarrer une nouvelle question - les commentaires ne sont pas le lieu. Vous pouvez toujours le lien vers celui-ci pour le contexte.pg_roles
, ce qui semble assez peu probable.Ou si le rôle n'est pas le propriétaire de la db objets que l'on peut utiliser:
Mais seulement en cas de suppression de cet utilisateur ne fera pas de mal.
La accepté de répondre souffre d'une condition de concurrence si deux de ces scripts sont exécutés simultanément sur le même Postgres cluster (serveur de base de données), comme c'est souvent le en continu-les environnements d'intégration.
Il est généralement plus sûr d'essayer de créer le rôle et gracieusement à faire face à des problèmes lors de sa création:
Bash alternative (pour scripts Bash):
(n'est-ce pas la réponse pour la question! c'est seulement pour ceux qui peuvent être utiles)
FROM pg_roles WHERE rolname
au lieu deFROM pg_user WHERE usename
Ici est une solution générique à l'aide de plpgsql:
Utilisation:
Que vous êtes sur 9.x, vous pouvez l'envelopper dans un énoncé:
Mon équipe était de frapper une situation avec plusieurs bases de données sur un serveur, en fonction de la base de données vous connecté à, le RÔLE en question n'a pas été retourné par
SELECT * FROM pg_catalog.pg_user
, tel que proposé par @erwin-brandstetter et @a_horse_with_no_name. Le bloc conditionnel exécuté, et nous a frappérole "my_user" already exists
.Malheureusement nous ne sommes pas sûr de conditions exactes, mais cette solution fonctionne de contourner le problème:
Il pourrait sans doute être plus précis pour exclure d'autres exceptions.
Vous pouvez le faire dans votre fichier de commandes par l'analyse de la sortie de:
puis en exécutant
psql.exe
une fois de plus, si le rôle n'existe pas.Quelques réponses a suggéré d'utiliser le modèle: vérifier si le rôle n'existe pas et si elle n'est pas alors question
CREATE ROLE
de commande. Cela a un inconvénient: condition de course. Si quelqu'un d'autre crée un nouveau rôle entre la vérification et la délivrance deCREATE ROLE
commande puisCREATE ROLE
évidemment échoue avec l'erreur fatale.Pour résoudre problème ci-dessus, plus d'autres réponses déjà mentionné l'utilisation de
PL/pgSQL
, l'émission deCREATE ROLE
inconditionnellement, puis attraper les exceptions de cet appel. Il y a juste un problème avec ces solutions. Ils silencieusement tomber toutes les erreurs, y compris celles qui ne sont pas générés par le fait que ce rôle existe déjà.CREATE ROLE
pouvez lancer aussi sur d'autres erreurs et de simulationIF NOT EXISTS
devrait silence seulement d'erreur lors de rôle existe déjà.CREATE ROLE
jeterduplicate_object
erreur lors de rôle existe déjà. Et gestionnaire d'exception doit attraper cette seule erreur. Comme d'autres réponses mentionné, c'est une bonne idée de convertir erreur fatale d'un simple avis. D'autres PostgreSQLIF NOT EXISTS
commandes ajoute, skipping
dans leur message, donc pour des raisons de cohérence, je suis en ajoutant ici aussi.Ici est plein de code SQL pour la simulation de
CREATE ROLE IF NOT EXISTS
avec exception correcte et sqlstate de propagation:De sortie de Test (appelé deux fois via NE puis directement):
La même solution que pour Simuler CRÉER une BASE de données SI n'EXISTE PAS pour PostgreSQL? travail - envoyer un
CREATE USER …
à\gexec
.Solution de contournement de l'intérieur psql
Solution de contournement de la coquille
Voir accepté réponse pour plus de détails.