¿Cómo escribo un script SQL para crear un ROL 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 simple y me gustaría evitar PL / pgSQL y demás, si es posible.
$
tiene un significado especial en su cliente, debe escapar de acuerdo con las reglas de sintaxis de su cliente. Intente escapar$
con\$
el shell de Linux. O comience una nueva pregunta: los comentarios no son el lugar. Siempre puede vincular a este para el contexto.La respuesta aceptada sufre una condición de carrera si dos de estos scripts se ejecutan simultáneamente en el mismo clúster de Postgres (servidor de base de datos), como es común en los entornos de integración continua .
Por lo general, es más seguro intentar crear el rol y tratar con elegancia los problemas al crearlo:
fuente
DUPLICATE_OBJECT
es la condición precisa en este caso, si no desea detectar casi todas las condiciones conOTHERS
.O si el rol no es el propietario de ningún objeto db, se puede usar:
Pero solo si dejar caer a este usuario no hará ningún daño.
fuente
Alternativa de Bash (para scripts de Bash ):
(¡No es la respuesta a la pregunta! Es solo para aquellos que pueden ser útiles)
fuente
FROM pg_roles WHERE rolname
lugar deFROM pg_user WHERE usename
Aquí hay una solución genérica que usa plpgsql:
Uso:
fuente
Algunas respuestas sugirieron usar patrón: verifique si el rol no existe y si no, emita el
CREATE ROLE
comando. Esto tiene una desventaja: condición de carrera. Si alguien más crea un nuevo rol entre la verificación y la emisión delCREATE ROLE
comando,CREATE ROLE
obviamente falla con un error fatal.Para resolver el problema anterior, más otras respuestas ya mencionaron el uso de
PL/pgSQL
, emitiendoCREATE ROLE
incondicionalmente y luego capturando excepciones de esa llamada. Solo hay un problema con estas soluciones. Eliminan silenciosamente cualquier error, incluidos los que no se generan por el hecho de que el rol ya existe.CREATE ROLE
puede arrojar también otros errores y la simulaciónIF NOT EXISTS
debe silenciar solo el error cuando el rol ya existe.CREATE ROLE
arrojarduplicate_object
error cuando el rol ya existe. Y el controlador de excepciones debería detectar solo este error. Como se mencionó en otras respuestas, es una buena idea convertir un error fatal en un simple aviso. SeIF NOT EXISTS
agregan otros comandos de PostgreSQL, skipping
a su mensaje, por lo que para mantener la coherencia, también lo agrego aquí.Aquí está el código SQL completo para la simulación
CREATE ROLE IF NOT EXISTS
con la excepción correcta y la propagación de sqlstate:Salida de prueba (llamada dos veces a través de DO y luego directamente):
fuente
Como está en 9.x, puede envolver eso en una declaración DO:
fuente
Mi equipo estaba enfrentando una situación con múltiples bases de datos en un servidor, según la base de datos a la que se conectó, el ROLE en cuestión no fue devuelto por
SELECT * FROM pg_catalog.pg_user
, como lo propusieron @ erwin-brandstetter y @a_horse_with_no_name. El bloque condicional se ejecutó y acertamosrole "my_user" already exists
.Desafortunadamente, no estamos seguros de las condiciones exactas, pero esta solución soluciona el problema:
Probablemente podría hacerse más específico para descartar otras excepciones.
fuente
Puede hacerlo en su archivo por lotes analizando la salida de:
y luego ejecutarse
psql.exe
una vez más si el rol no existe.fuente
¿La misma solución que para Simulate CREATE DATABASE SI NO EXISTE para PostgreSQL? debería funcionar - enviar un
CREATE USER …
a\gexec
.Solución alternativa desde psql
Solución alternativa desde el caparazón
Consulte la respuesta aceptada allí para obtener más detalles.
fuente