Comment vérifier si un utilisateur postgres existe?

89

createuserpermet la création d'un utilisateur (ROLE) dans PostgreSQL. Existe-t-il un moyen simple de vérifier si cet utilisateur (nom) existe déjà? Sinon, createuser revient avec une erreur:

createuser: creation of new role failed: ERROR:  role "USR_NAME" already exists

MISE À JOUR: La solution doit être exécutable à partir du shell de préférence, afin qu'il soit plus facile d'automatiser à l'intérieur d'un script.

m33lky
la source

Réponses:

158
SELECT 1 FROM pg_roles WHERE rolname='USR_NAME'

Et en termes de ligne de commande (merci à Erwin):

psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='USR_NAME'"

Donne 1 s'il est trouvé et rien d'autre.

C'est:

psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='USR_NAME'" | grep -q 1 || createuser ...
Michael Krelin - hacker
la source
Vous souvenez-vous de l'utilitaire de ligne de commande intégré pour exécuter SQL? En fin de compte, je préférerais exécuter et récupérer le résultat du shell si possible.
m33lky
1
psqlest la commande. Mais si vous parlez d' createuserutilitaire de ligne de commande (vous le faites évidemment, je n'ai pas remarqué le manque d'espace create userau début), alors il peut être plus facile d'ignorer simplement l'état de sortie et de rediriger la sortie vers /dev/null.
Michael Krelin - hacker
2
@ m33lky: Ou vous pouvez tester la valeur de retour de cette commande dans le shell ( en tant qu'utilisateur postgres): psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='USR_NAME'". Rend 1s'il est trouvé et rien d'autre.
Erwin Brandstetter
1
Haha, je viens de le faire que d'une manière peu plus laid: echo "SELECT rolname FROM pg_roles WHERE rolname='USR_NAME';" | psql | grep -c USR_NAME. Ajoutez votre solution comme réponse sans "postgres" après psql.
m33lky
2
@ m33lky: Je n'ai écrit qu'un commentaire, car je pense que Michael mérite le crédit sur celui-ci. Il a contribué la partie principale. Et il s'est avéré être un bon sport dans le passé. :) Peut-être que Michael veut l'intégrer dans sa réponse?
Erwin Brandstetter
5

Suivre la même idée que de vérifier si une base de données existe

psql -t -c '\du' | cut -d \| -f 1 | grep -qw <user_to_check>

et vous pouvez l'utiliser dans un script comme celui-ci:

if psql -t -c '\du' | cut -d \| -f 1 | grep -qw <user_to_check>; then
    # user exists
    # $? is 0
else
    # ruh-roh
    # $? is 1
fi
mat
la source
Cela générerait un résultat de requête plus grand que la réponse stackoverflow.com/a/8546783/107158 . Cependant, contrairement à cette réponse, celle-ci survivrait à un changement de nom en table système pg_roles, mais pas à un changement de commande \du. Qu'est-ce qui ne changera probablement pas?
Derek Mahar
3

J'espère que cela aidera ceux d'entre vous qui pourraient faire cela en python .
J'ai créé un script / solution de travail complet sur un GitHubGist - voir l'URL ci-dessous cet extrait de code.

# ref: /programming/8546759/how-to-check-if-a-postgres-user-exists
check_user_cmd = ("SELECT 1 FROM pg_roles WHERE rolname='%s'" % (deis_app_user))

# our create role/user command and vars
create_user_cmd = ("CREATE ROLE %s WITH LOGIN CREATEDB PASSWORD '%s'" % (deis_app_user, deis_app_passwd))

# ref: /programming/37488175/simplify-database-psycopg2-usage-by-creating-a-module
class RdsCreds():
    def __init__(self):
        self.conn = psycopg2.connect("dbname=%s user=%s host=%s password=%s" % (admin_db_name, admin_db_user, db_host, admin_db_pass))
        self.conn.set_isolation_level(0)
        self.cur = self.conn.cursor()

    def query(self, query):
        self.cur.execute(query)
        return self.cur.rowcount > 0

    def close(self):
        self.cur.close()
        self.conn.close()

db = RdsCreds()
user_exists = db.query(check_user_cmd)

# PostgreSQL currently has no 'create role if not exists'
# So, we only want to create the role/user if not exists 
if (user_exists) is True:
    print("%s user_exists: %s" % (deis_app_user, user_exists))
    print("Idempotent: No credential modifications required. Exiting...")
    db.close()
else:
    print("%s user_exists: %s" % (deis_app_user, user_exists))
    print("Creating %s user now" % (deis_app_user))
    db.query(create_user_cmd)
    user_exists = db.query(check_user_cmd)
    db.close()
    print("%s user_exists: %s" % (deis_app_user, user_exists))

Fournit un rôle / utilisateur de création PostgreSQL distant idempotent (RDS) à partir de python sans modules CM, etc.

cmcc
la source
1

psql -qtA -c "\du USR_NAME" | cut -d "|" -f 1

[[ -n $(psql -qtA -c "\du ${1}" | cut -d "|" -f 1) ]] && echo "exists" || echo "does not exist"

Pascal Polleunus
la source