Một số câu trả lời được đề xuất để sử dụng mẫu: kiểm tra nếu vai trò không tồn tại và nếu không thì hãy ra CREATE ROLElệnh. Điều này có một bất lợi: điều kiện chủng tộc. Nếu ai đó khác tạo một vai trò mới giữa kiểm tra và phát hành CREATE ROLElệnh thì CREATE ROLErõ ràng là không thành công với lỗi nghiêm trọng.
Để giải quyết vấn đề trên, nhiều câu trả lời khác đã đề cập đến việc sử dụng PL/pgSQL, phát hành CREATE ROLEvô điều kiện và sau đó bắt các ngoại lệ từ cuộc gọi đó. Chỉ có một vấn đề với các giải pháp này. Họ âm thầm loại bỏ bất kỳ lỗi nào, bao gồm cả những lỗi không được tạo ra bởi thực tế rằng vai trò đã tồn tại. CREATE ROLEcũng có thể tạo ra các lỗi khác và mô phỏng IF NOT EXISTSchỉ nên tắt lỗi khi vai trò đã tồn tại.
CREATE ROLEném duplicate_objectlỗi khi vai trò đã tồn tại. Và trình xử lý ngoại lệ chỉ nên bắt một lỗi này. Như các câu trả lời khác đã đề cập, bạn nên chuyển lỗi nghiêm trọng thành thông báo đơn giản. Các IF NOT EXISTSlệnh PostgreSQL khác thêm , skippingvào thông điệp của chúng, vì vậy để nhất quán, tôi cũng sẽ thêm nó vào đây.
Đây là mã SQL đầy đủ để mô phỏng CREATE ROLE IF NOT EXISTSvới sự lan truyền ngoại lệ và sqlstate chính xác:
DO $$
BEGIN
CREATE ROLE test;
EXCEPTION WHEN duplicate_object THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
END
$$;
Kiểm tra đầu ra (được gọi hai lần qua DO và sau đó trực tiếp):
$ 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