Bazı yanıtlar kalıbı kullanmayı önerdi: rolün var olup olmadığını kontrol edin ve yoksa CREATE ROLEkomut verin. Bunun bir dezavantajı var: yarış durumu. Başka biri kontrol etme ve verme CREATE ROLEkomutu arasında yeni bir rol yaratırsa, o zamanCREATE ROLE açıkça ölümcül bir hatayla başarısız olur.
Soruna yukarıda çözmek için, daha başka cevaplar zaten kullanımını söz PL/pgSQLveren, CREATE ROLEkoşulsuz ve daha sonra bu çağrısından durumları yakalamak. Bu çözümlerle ilgili yalnızca bir sorun var. Rolün zaten var olduğu gerçeğiyle oluşmayanlar da dahil olmak üzere tüm hataları sessizce atarlar. CREATE ROLEbaşka hatalar da atabilir ve simülasyon IF NOT EXISTSyalnızca rol zaten mevcut olduğunda hatayı susturmalıdır.
CREATE ROLEatmak duplicate_objectrolü zaten var olduğunda hata. Ve istisna işleyicisi yalnızca bu tek hatayı yakalamalıdır. Diğer cevaplarda belirtildiği gibi, ölümcül hatayı basit bildirime dönüştürmek iyi bir fikirdir. Diğer PostgreSQL IF NOT EXISTSkomutları , skippingmesajlarına ekler , bu nedenle tutarlılık için buraya da ekliyorum.
CREATE ROLE IF NOT EXISTSDoğru istisna ve sqlstate yayılımı ile simülasyonu için tam SQL kodu :
DO $$
BEGIN
CREATE ROLE test;
EXCEPTION WHEN duplicate_object THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
END
$$;
Test çıkışı (DO aracılığıyla iki kez ve ardından doğrudan çağrılır):
$ 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