PostgreSQL tidak mendukung IF NOT EXISTS
untuk CREATE DATABASE
pernyataan. Ini hanya didukung di CREATE SCHEMA
. Apalagi CREATE DATABASE
tidak bisa dikeluarkan dalam transaksi sehingga tidak bisa di DO
blok dengan exception catching.
Kapan CREATE SCHEMA IF NOT EXISTS
dikeluarkan dan skema sudah ada maka pemberitahuan (bukan kesalahan) dengan informasi objek duplikat dimunculkan.
Untuk mengatasi masalah ini, Anda perlu menggunakan dblink
ekstensi yang membuka koneksi baru ke server database dan menjalankan kueri tanpa melakukan transaksi. Anda dapat menggunakan kembali parameter koneksi dengan menyediakan string kosong.
Di bawah ini adalah PL/pgSQL
kode yang sepenuhnya disimulasikan CREATE DATABASE IF NOT EXISTS
dengan perilaku yang sama seperti di CREATE SCHEMA IF NOT EXISTS
. Ini memanggil CREATE DATABASE
melalui dblink
, catch duplicate_database
exception (yang dikeluarkan ketika database sudah ada) dan mengubahnya menjadi notice dengan menyebarkan errcode
. Pesan string telah ditambahkan , skipping
dengan cara yang sama seperti yang dilakukannya 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
$$;
Solusi ini tanpa kondisi balapan seperti di jawaban lain, di mana database dapat dibuat dengan proses eksternal (atau contoh lain dari skrip yang sama) antara memeriksa apakah database ada dan pembuatannya sendiri.
Selain itu ketika CREATE DATABASE
gagal dengan kesalahan selain database sudah ada maka kesalahan ini disebarkan sebagai kesalahan dan tidak diam-diam dibuang. Hanya ada menangkap duplicate_database
kesalahan. Jadi benar-benar berperilaku sebagaimana IF NOT EXISTS
mestinya.
Anda dapat memasukkan kode ini ke dalam fungsi sendiri, memanggilnya langsung atau dari transaksi. Hanya rollback (mengembalikan database yang jatuh) tidak akan berfungsi.
Menguji keluaran (dipanggil dua kali melalui DO dan kemudian secara langsung):
$ 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
.