Einige Antworten schlagen vor, Muster zu verwenden: Überprüfen Sie, ob keine Rolle vorhanden ist, und geben Sie dann einen CREATE ROLE
Befehl aus. Dies hat einen Nachteil: Rennbedingung. Wenn jemand anderes eine neue Rolle zwischen Prüfung und Ausgabe des CREATE ROLE
Befehls erstellt, dannCREATE ROLE
schlägt dies offensichtlich mit einem schwerwiegenden Fehler fehl.
Um das obige Problem zu lösen, erwähnten weitere Antworten bereits die Verwendung von PL/pgSQL
, CREATE ROLE
bedingungslose Ausgabe und dann das Abfangen von Ausnahmen von diesem Aufruf. Bei diesen Lösungen gibt es nur ein Problem. Sie löschen stillschweigend alle Fehler, einschließlich solcher, die nicht durch die Tatsache generiert werden, dass die Rolle bereits vorhanden ist. CREATE ROLE
kann auch andere Fehler auslösen und die Simulation IF NOT EXISTS
sollte nur Fehler zum Schweigen bringen, wenn die Rolle bereits vorhanden ist.
CREATE ROLE
duplicate_object
Fehler auslösen , wenn die Rolle bereits vorhanden ist. Und der Ausnahmebehandler sollte nur diesen einen Fehler abfangen. Wie in anderen Antworten erwähnt, ist es eine gute Idee, schwerwiegende Fehler in einfache Hinweise umzuwandeln. Andere PostgreSQL- IF NOT EXISTS
Befehle fügen , skipping
ihrer Nachricht hinzu. Aus Gründen der Konsistenz füge ich sie auch hier hinzu.
Hier ist der vollständige SQL-Code für die Simulation CREATE ROLE IF NOT EXISTS
mit korrekter Ausnahme und SQLstate-Weitergabe:
DO $$
BEGIN
CREATE ROLE test;
EXCEPTION WHEN duplicate_object THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
END
$$;
Testausgabe (zweimal über DO und dann direkt aufgerufen):
$ sudo -u postgres psql
psql (9.6.12)
Type "help" for help.
postgres=# \set ON_ERROR_STOP on
postgres=# \set VERBOSITY verbose
postgres=#
postgres=# DO $$
postgres$# BEGIN
postgres$# CREATE ROLE test;
postgres$# EXCEPTION WHEN duplicate_object THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
postgres$# END
postgres$# $$;
DO
postgres=#
postgres=# DO $$
postgres$# BEGIN
postgres$# CREATE ROLE test;
postgres$# EXCEPTION WHEN duplicate_object THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
postgres$# END
postgres$# $$;
NOTICE: 42710: role "test" already exists, skipping
LOCATION: exec_stmt_raise, pl_exec.c:3165
DO
postgres=#
postgres=# CREATE ROLE test;
ERROR: 42710: role "test" already exists
LOCATION: CreateRole, user.c:337