usuarios usuario rol postgres nuevo lista grupos entre diferencia crear consultar como administrar sql postgresql roles dynamic-sql

rol - postgresql lista de usuarios



Crear ROLE de PostgreSQL(usuario) si no existe (8)

¿Cómo escribo un script SQL para crear un ROLE en PostgreSQL 9.1, pero sin generar un error si ya existe?

El script actual simplemente tiene:

CREATE ROLE my_user LOGIN PASSWORD ''my_password'';

Esto falla si el usuario ya existe. Me gustaría algo como:

IF NOT EXISTS (SELECT * FROM pg_user WHERE username = ''my_user'') BEGIN CREATE ROLE my_user LOGIN PASSWORD ''my_password''; END;

... pero eso no funciona - IF no parece ser compatible con SQL simple.

Tengo un archivo por lotes que crea una base de datos PostgreSQL 9.1, un rol y algunas otras cosas. Llama a psql.exe, pasando el nombre de un script SQL para ejecutar. Hasta ahora, todos estos scripts son SQL simples y me gustaría evitar PL / pgSQL y tal, si es posible.


Alternativa Bash (para scripts Bash ):

psql -h localhost -U postgres -tc "SELECT 1 FROM pg_user WHERE usename = ''my_user''" | grep -q 1 || psql -h localhost -U postgres -c "CREATE ROLE my_user LOGIN PASSWORD ''my_password'';"

(¡No es la respuesta para la pregunta! Es solo para aquellos que pueden ser útiles)


Aquí hay una solución genérica usando plpgsql:

CREATE OR REPLACE FUNCTION create_role_if_not_exists(rolename NAME) RETURNS TEXT AS $$ BEGIN IF NOT EXISTS (SELECT * FROM pg_roles WHERE rolname = rolename) THEN EXECUTE format(''CREATE ROLE %I'', rolename); RETURN ''CREATE ROLE''; ELSE RETURN format(''ROLE ''''%I'''' ALREADY EXISTS'', rolename); END IF; END; $$ LANGUAGE plpgsql;

Uso:

posgres=# SELECT create_role_if_not_exists(''ri''); create_role_if_not_exists --------------------------- CREATE ROLE (1 row) posgres=# SELECT create_role_if_not_exists(''ri''); create_role_if_not_exists --------------------------- ROLE ''ri'' ALREADY EXISTS (1 row)


Como está en 9.x, puede incluirlo en una declaración DO:

do $body$ declare num_users integer; begin SELECT count(*) into num_users FROM pg_user WHERE usename = ''my_user''; IF num_users = 0 THEN CREATE ROLE my_user LOGIN PASSWORD ''my_password''; END IF; end $body$ ;


La respuesta aceptada adolece de una condición de carrera si dos de dichos scripts se ejecutan simultáneamente en el mismo clúster de Postgres (servidor de base de datos), como es habitual en entornos de integración continua .

Por lo general, es más seguro intentar crear el rol y tratar con gracia los problemas al crearlo:

DO $$ BEGIN CREATE ROLE my_role WITH NOLOGIN; EXCEPTION WHEN OTHERS THEN RAISE NOTICE ''not creating role my_role -- it already exists''; END $$;


Mi equipo estaba solucionando una situación con varias bases de datos en un servidor, dependiendo de la base de datos a la que se conectara, el PAPEL en cuestión no fue devuelto por SELECT * FROM pg_catalog.pg_user , tal como lo propusieron @ erwin-brandstetter y @a_horse_with_no_name. El bloque condicional ejecutado, y llegamos al role "my_user" already exists .

Lamentablemente, no estamos seguros de las condiciones exactas, pero esta solución funciona alrededor del problema:

DO $body$ BEGIN CREATE ROLE my_user LOGIN PASSWORD ''my_password''; EXCEPTION WHEN others THEN RAISE NOTICE ''my_user role exists, not re-creating''; END $body$

Probablemente podría hacerse más específico para descartar otras excepciones.


O si el rol no es el propietario de ningún objeto db uno puede usar:

DROP ROLE IF EXISTS my_user; CREATE ROLE my_user LOGIN PASSWORD ''my_password'';

Pero solo si dejar caer este usuario no hará ningún daño.


Puede hacerlo en su archivo por lotes analizando la salida de:

SELECT * FROM pg_user WHERE usename = ''my_user''

y luego ejecutar psql.exe una vez más si el rol no existe.


Simplifica de manera similar a lo que tenías en mente:

DO $do$ BEGIN IF NOT EXISTS ( SELECT -- SELECT list can stay empty for this FROM pg_catalog.pg_roles WHERE rolname = ''my_user'') THEN CREATE ROLE my_user LOGIN PASSWORD ''my_password''; END IF; END $do$;

(Basándose en la respuesta de @a_horse_with_no_name y mejorado después del comentario de @a_horse_with_no_name ).

A diferencia, por ejemplo, con CREATE TABLE no existe la cláusula IF NOT EXISTS para CREATE ROLE (todavía). Y no puede ejecutar sentencias DDL dinámicas en SQL puro.

Su solicitud para "evitar PL / pgSQL" es imposible, excepto al utilizar otro PL. La declaración DO utiliza plpgsql como lenguaje de procedimiento predeterminado. La sintaxis permite omitir la declaración explícita:

] code DO [ LANGUAGE lang_name ] code
...
lang_name
El nombre del lenguaje de procedimiento en el que está escrito el código. Si se omite, el valor predeterminado es plpgsql .