PostgreSQL không hỗ trợ IF NOT EXISTS
cho CREATE DATABASE
câu lệnh. Nó chỉ được hỗ trợ trong CREATE SCHEMA
. Hơn nữa, CREATE DATABASE
không thể được phát hành trong giao dịch do đó nó không thể nằm trong DO
khối với việc bắt ngoại lệ.
Khi nào CREATE SCHEMA IF NOT EXISTS
được phát hành và lược đồ đã tồn tại thì thông báo (không phải lỗi) với thông tin đối tượng trùng lặp được đưa ra.
Để giải quyết những vấn đề này, bạn cần sử dụng dblink
tiện ích mở rộng mở một kết nối mới đến máy chủ cơ sở dữ liệu và thực hiện truy vấn mà không cần tham gia giao dịch. Bạn có thể sử dụng lại các tham số kết nối với việc cung cấp chuỗi trống.
Dưới đây là PL/pgSQL
mã mô phỏng đầy đủ CREATE DATABASE IF NOT EXISTS
với hành vi tương tự như trong CREATE SCHEMA IF NOT EXISTS
. Nó gọi CREATE DATABASE
thông qua dblink
, bắt duplicate_database
ngoại lệ (được phát hành khi cơ sở dữ liệu đã tồn tại) và chuyển nó thành thông báo với việc truyền bá errcode
. Thông báo chuỗi đã được nối , skipping
theo cách tương tự như cách thực hiện CREATE SCHEMA IF NOT EXISTS
.
CREATE EXTENSION IF NOT EXISTS dblink;
DO $$
BEGIN
PERFORM dblink_exec('', 'CREATE DATABASE testdb');
EXCEPTION WHEN duplicate_database THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
END
$$;
Giải pháp này không có bất kỳ điều kiện chạy đua nào như trong các câu trả lời khác, trong đó cơ sở dữ liệu có thể được tạo bằng quy trình bên ngoài (hoặc trường hợp khác của cùng một tập lệnh) giữa việc kiểm tra xem cơ sở dữ liệu có tồn tại và việc tạo riêng của nó hay không.
Hơn nữa, khi CREATE DATABASE
không thành công với lỗi khác với cơ sở dữ liệu đã tồn tại thì lỗi này được coi là lỗi và không bị loại bỏ một cách âm thầm. Chỉ có bắt duplicate_database
lỗi. Vì vậy, nó thực sự hoạt động như IF NOT EXISTS
nên.
Bạn có thể đặt mã này vào chức năng riêng, gọi trực tiếp hoặc từ giao dịch. Chỉ khôi phục lại (khôi phục cơ sở dữ liệu bị bỏ) sẽ không hoạt động.
Kiểm tra đầu ra (được gọi hai lần thông 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=# CREATE EXTENSION IF NOT EXISTS dblink;
CREATE EXTENSION
postgres=# DO $$
postgres$# BEGIN
postgres$# PERFORM dblink_exec('', 'CREATE DATABASE testdb');
postgres$# EXCEPTION WHEN duplicate_database THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
postgres$# END
postgres$# $$;
DO
postgres=#
postgres=# CREATE EXTENSION IF NOT EXISTS dblink;
NOTICE: 42710: extension "dblink" already exists, skipping
LOCATION: CreateExtension, extension.c:1539
CREATE EXTENSION
postgres=# DO $$
postgres$# BEGIN
postgres$# PERFORM dblink_exec('', 'CREATE DATABASE testdb');
postgres$# EXCEPTION WHEN duplicate_database THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
postgres$# END
postgres$# $$;
NOTICE: 42P04: database "testdb" already exists, skipping
LOCATION: exec_stmt_raise, pl_exec.c:3165
DO
postgres=#
postgres=# CREATE DATABASE testdb;
ERROR: 42P04: database "testdb" already exists
LOCATION: createdb, dbcommands.c:467
dblink_connect
.