पैटर्न का उपयोग करने के लिए सुझाए गए कुछ उत्तर: जांचें कि क्या भूमिका मौजूद नहीं है और यदि नहीं तो CREATE ROLEकमांड जारी करें । इसका एक नुकसान है: दौड़ की स्थिति। यदि कोई अन्य व्यक्ति चेक और जारी करने वाले CREATE ROLEकमांड के बीच एक नई भूमिका बनाता है, तो CREATE ROLEस्पष्ट रूप से घातक त्रुटि के साथ विफल हो जाता है।
उपरोक्त समस्या को हल करने के लिए, पहले से उपयोग किए गए PL/pgSQL, CREATE ROLEबिना किसी शर्त के , और फिर उस कॉल के अपवादों को पकड़ने के लिए पहले से वर्णित अन्य उत्तरों का उपयोग किया गया है। इन समाधानों के साथ सिर्फ एक समस्या है। वे चुपचाप किसी भी त्रुटि को छोड़ देते हैं, जिसमें वे इस तथ्य से उत्पन्न नहीं होते हैं कि भूमिका पहले से मौजूद है। CREATE ROLEअन्य त्रुटियों को भी फेंक सकते हैं और सिमुलेशन IF NOT EXISTSको केवल त्रुटि को चुप करना चाहिए जब भूमिका पहले से मौजूद है।
CREATE ROLEduplicate_objectभूमिका पहले से मौजूद होने पर त्रुटि फेंकें । और अपवाद हैंडलर को केवल इस एक त्रुटि को पकड़ना चाहिए। जैसा कि अन्य उत्तरों ने उल्लेख किया है कि घातक त्रुटि को सरल नोटिस में बदलना एक अच्छा विचार है। अन्य PostgreSQL IF NOT EXISTSकमांड , skippingउनके संदेश में जोड़ता है , इसलिए स्थिरता के लिए मैं इसे यहां भी जोड़ रहा हूं।
CREATE ROLE IF NOT EXISTSसही अपवाद और sqlstate प्रसार के अनुकरण के लिए यहां पूर्ण SQL कोड है :
DO $$
BEGIN
CREATE ROLE test;
EXCEPTION WHEN duplicate_object THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
END
$$;
टेस्ट आउटपुट (दो बार के माध्यम से और फिर सीधे कहा जाता है):
$ 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