Batasan
Anda dapat meminta katalog sistem pg_database
- dapat diakses dari database mana pun di cluster database yang sama. Bagian yang sulit adalah yang CREATE DATABASE
hanya dapat dijalankan sebagai satu pernyataan. Manualnya:
CREATE DATABASE
tidak dapat dieksekusi di dalam blok transaksi.
Jadi tidak bisa dijalankan langsung di dalam fungsi atau DO
pernyataan, di mana itu akan berada di dalam blok transaksi secara implisit.
(Prosedur SQL, diperkenalkan dengan Postgres 11, tidak dapat membantu dengan ini juga .)
Solusi dari dalam psql
Anda dapat mengatasinya dari dalam psql dengan menjalankan pernyataan DDL secara bersyarat:
SELECT 'CREATE DATABASE mydb'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec
Manualnya:
\gexec
Mengirim buffer kueri saat ini ke server, kemudian memperlakukan setiap kolom dari setiap baris dari output kueri (jika ada) sebagai pernyataan SQL yang akan dieksekusi.
Solusi dari shell
Dengan \gexec
Anda hanya perlu memanggil psql sekali :
echo "SELECT 'CREATE DATABASE mydb' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec" | psql
Anda mungkin membutuhkan lebih banyak opsi psql untuk koneksi Anda; role, port, password, ... Lihat:
Hal yang sama tidak dapat dipanggil dengan psql -c "SELECT ...\gexec"
karena \gexec
adalah perintah psql meta ‑ dan -c
opsi mengharapkan satu perintah yang dinyatakan manual:
command
harus berupa string perintah yang dapat diurai sepenuhnya oleh server (yaitu, tidak berisi fitur khusus psql), atau satu perintah garis miring terbalik. Dengan demikian Anda tidak dapat mencampur meta-command SQL dan psql dalam sebuah -c
opsi.
Solusi dari dalam transaksi Postgres
Anda bisa menggunakan dblink
koneksi kembali ke database saat ini, yang berjalan di luar blok transaksi. Oleh karena itu, Efek juga tidak dapat diputar kembali.
Instal dblink modul tambahan untuk ini (sekali per database):
Kemudian:
DO
$do$
BEGIN
IF EXISTS (SELECT FROM pg_database WHERE datname = 'mydb') THEN
RAISE NOTICE 'Database already exists'; -- optional
ELSE
PERFORM dblink_exec('dbname=' || current_database() -- current db
, 'CREATE DATABASE mydb');
END IF;
END
$do$;
Sekali lagi, Anda mungkin membutuhkan lebih banyak opsi psql untuk koneksi tersebut. Lihat jawaban tambahan Ortwin:
Penjelasan mendetail untuk dblink:
Anda dapat membuat fungsi ini untuk penggunaan berulang.
dblink_connect
.\gexec
saat menjalankan kueri pertama dari shell, tetapi berhasil.alternatif lain, untuk berjaga-jaga jika Anda ingin memiliki skrip shell yang membuat database jika tidak ada dan jika tidak, simpan saja apa adanya:
Saya menemukan ini berguna dalam skrip penyediaan devops, yang mungkin ingin Anda jalankan beberapa kali dalam contoh yang sama.
sumber
c:\Program Files\PostgreSQL\9.6\bin $ psql.exe -U admin -tc "SELECT 1 FROM pg_database WHERE datname = 'my_db'" | grep -q 1 || psql -U admin -c "CREATE DATABASE my_db" 'grep' is not recognized as an internal or external command, operable program or batch file.
Apa kesalahan yang telah aku perbuat ?grep
menghalangi jalan Anda. Di Windows,grep
tidak diinstal secara default. Anda dapat mencari untukgnu grep windows
menemukan versi yang dapat bekerja di Windows.Saya harus menggunakan versi yang sedikit diperpanjang @Erwin Brandstetter digunakan:
Saya harus mengaktifkan
dblink
ekstensi, ditambah lagi saya harus memberikan kredensial untuk dblink. Bekerja dengan Postgres 9.4.sumber
Jika Anda tidak peduli dengan datanya, Anda dapat melepaskan database terlebih dahulu, lalu membuatnya kembali:
sumber
PostgreSQL tidak mendukung
IF NOT EXISTS
untukCREATE DATABASE
pernyataan. Ini hanya didukung diCREATE SCHEMA
. ApalagiCREATE DATABASE
tidak bisa dikeluarkan dalam transaksi sehingga tidak bisa diDO
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 disimulasikanCREATE DATABASE IF NOT EXISTS
dengan perilaku yang sama seperti diCREATE SCHEMA IF NOT EXISTS
. Ini memanggilCREATE DATABASE
melaluidblink
, catchduplicate_database
exception (yang dikeluarkan ketika database sudah ada) dan mengubahnya menjadi notice dengan menyebarkanerrcode
. Pesan string telah ditambahkan, skipping
dengan cara yang sama seperti yang dilakukannyaCREATE SCHEMA IF NOT EXISTS
.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 menangkapduplicate_database
kesalahan. Jadi benar-benar berperilaku sebagaimanaIF 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):
sumber
Jika Anda bisa menggunakan shell, coba
Menurut saya
psql -U postgres -c "select 1" -d $DB
lebih mudah daripadaSELECT 1 FROM pg_database WHERE datname = 'my_db'
, dan hanya membutuhkan satu jenis kutipan, lebih mudah digabungkansh -c
.Saya menggunakan ini dalam tugas saya yang mungkin
sumber
Cukup buat database menggunakan
createdb
alat CLI:Jika database ada, itu akan mengembalikan kesalahan:
sumber
Tingkatkan ke PostgreSQL 9.5 atau yang lebih baru. Jika (tidak) ada diperkenalkan di versi 9.5.
sumber
if not exists
untukCREATE DATABASE
- bahkan di Postgres 11 postgresql.org/docs/current/static/sql-createdatabase.html