คำตอบบางคำแนะนำให้ใช้รูปแบบ: ตรวจสอบว่าไม่มีบทบาทอยู่หรือไม่และหากไม่มีให้ออกCREATE ROLE
คำสั่ง สิ่งนี้มีข้อเสียอย่างหนึ่งคือสภาพการแข่งขัน หากมีผู้อื่นสร้างบทบาทใหม่ระหว่างการตรวจสอบและการออกCREATE ROLE
คำสั่งจะCREATE ROLE
เห็นได้ชัดว่าล้มเหลวด้วยข้อผิดพลาดร้ายแรง
เพื่อแก้ปัญหาข้างต้นคำตอบอื่น ๆ ที่กล่าวถึงแล้วการใช้งานการPL/pgSQL
ออกCREATE ROLE
โดยไม่มีเงื่อนไขแล้วจับข้อยกเว้นจากการโทรนั้น มีเพียงปัญหาเดียวในการแก้ปัญหาเหล่านี้ พวกเขาทิ้งข้อผิดพลาดใด ๆ อย่างเงียบ ๆ รวมถึงข้อผิดพลาดที่ไม่ได้สร้างขึ้นจากข้อเท็จจริงที่มีบทบาทอยู่แล้ว CREATE ROLE
สามารถโยนข้อผิดพลาดอื่น ๆ ได้และการจำลองIF NOT EXISTS
ควรปิดเสียงข้อผิดพลาดเมื่อมีบทบาทอยู่แล้วเท่านั้น
CREATE ROLE
เกิดduplicate_object
ข้อผิดพลาดเมื่อมีบทบาทอยู่แล้ว และตัวจัดการข้อยกเว้นควรตรวจจับข้อผิดพลาดนี้เท่านั้น ดังคำตอบอื่น ๆ ที่กล่าวถึงเป็นความคิดที่ดีที่จะแปลงข้อผิดพลาดร้ายแรงเป็นการแจ้งให้ทราบล่วงหน้า IF NOT EXISTS
คำสั่งPostgreSQL อื่น ๆจะเพิ่ม, skipping
เข้าไปในข้อความของพวกเขาดังนั้นเพื่อความสอดคล้องฉันจะเพิ่มไว้ที่นี่ด้วย
นี่คือรหัส SQL แบบเต็มสำหรับการจำลองCREATE ROLE IF NOT EXISTS
ด้วยข้อยกเว้นที่ถูกต้องและการแพร่กระจายของ sqlstate:
DO $$
BEGIN
CREATE ROLE test;
EXCEPTION WHEN duplicate_object THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
END
$$;
ผลลัพธ์การทดสอบ (เรียกสองครั้งผ่าน DO จากนั้นโดยตรง):
$ 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