Bagaimana cara menulis skrip SQL untuk membuat ROLE di PostgreSQL 9.1, tetapi tanpa menimbulkan kesalahan jika sudah ada?
Skrip saat ini hanya memiliki:
CREATE ROLE my_user LOGIN PASSWORD 'my_password';
Ini gagal jika pengguna sudah ada. Saya ingin sesuatu seperti:
IF NOT EXISTS (SELECT * FROM pg_user WHERE username = 'my_user')
BEGIN
CREATE ROLE my_user LOGIN PASSWORD 'my_password';
END;
... tapi itu tidak berhasil - IF
sepertinya tidak didukung dalam SQL biasa.
Saya memiliki file batch yang membuat database PostgreSQL 9.1, peran, dan beberapa hal lainnya. Ini memanggil psql.exe, meneruskan nama skrip SQL untuk dijalankan. Sejauh ini semua skrip ini adalah SQL biasa dan saya ingin menghindari PL / pgSQL dan semacamnya, jika memungkinkan.
$
memiliki arti khusus pada klien Anda, Anda perlu menghindarinya sesuai dengan aturan sintaks klien Anda. Cobalah kabur$
dengan\$
di shell Linux. Atau mulai pertanyaan baru - komentar bukanlah tempatnya. Anda selalu dapat menautkan yang ini untuk konteks.Jawaban yang diterima menderita kondisi balapan jika dua skrip seperti itu dijalankan secara bersamaan di cluster Postgres yang sama (server DB), seperti yang umum di lingkungan integrasi berkelanjutan .
Biasanya lebih aman untuk mencoba membuat peran dan menangani masalah dengan baik saat membuatnya:
sumber
DUPLICATE_OBJECT
adalah kondisi yang tepat dalam kasus ini, jika Anda tidak ingin menangkap hampir semua kondisi denganOTHERS
.Atau jika role tersebut bukan pemilik objek db apa pun yang dapat digunakan:
Tetapi hanya jika menjatuhkan pengguna ini tidak akan merugikan.
sumber
Alternatif Bash (untuk skrip Bash ):
(bukan jawaban untuk pertanyaannya! ini hanya untuk mereka yang mungkin berguna)
sumber
FROM pg_roles WHERE rolname
sebagai penggantiFROM pg_user WHERE usename
Berikut adalah solusi umum menggunakan plpgsql:
Pemakaian:
sumber
Beberapa jawaban menyarankan untuk menggunakan pola: periksa apakah peran tidak ada dan jika tidak maka keluarkan
CREATE ROLE
perintah. Ini memiliki satu kelemahan: kondisi balapan. Jika orang lain membuat peran baru antara check dan mengeluarkanCREATE ROLE
perintah, makaCREATE ROLE
jelas gagal dengan kesalahan fatal.Untuk mengatasi masalah di atas, lebih banyak jawaban lain yang telah disebutkan penggunaan
PL/pgSQL
, mengeluarkanCREATE ROLE
tanpa syarat dan kemudian menangkap pengecualian dari panggilan itu. Hanya ada satu masalah dengan solusi ini. Mereka diam-diam menjatuhkan semua kesalahan, termasuk yang tidak dihasilkan oleh fakta bahwa peran sudah ada.CREATE ROLE
dapat membuang juga kesalahan lain dan simulasiIF NOT EXISTS
harus membungkam kesalahan hanya jika peran sudah ada.CREATE ROLE
melemparduplicate_object
kesalahan saat peran sudah ada. Dan penangan pengecualian harus menangkap hanya satu kesalahan ini. Seperti jawaban lain yang disebutkan, sebaiknya ubah kesalahan fatal menjadi pemberitahuan sederhana.IF NOT EXISTS
Perintah PostgreSQL lainnya menambahkan, skipping
ke dalam pesan mereka, jadi untuk konsistensi saya juga menambahkannya di sini.Berikut adalah kode SQL lengkap untuk simulasi
CREATE ROLE IF NOT EXISTS
dengan pengecualian yang benar dan propagasi sqlstate:Output tes (dipanggil dua kali melalui DO dan kemudian secara langsung):
sumber
Karena Anda berada di 9.x, Anda dapat menggabungkannya menjadi pernyataan DO:
sumber
Tim saya mengalami situasi dengan beberapa database di satu server, tergantung pada database mana Anda terhubung, PERAN yang dimaksud tidak dikembalikan oleh
SELECT * FROM pg_catalog.pg_user
, seperti yang diusulkan oleh @ erwin-brandstetter dan @a_horse_with_no_name. Blok bersyarat dieksekusi, dan kami menekanrole "my_user" already exists
.Sayangnya kami tidak yakin dengan kondisi pastinya, tetapi solusi ini mengatasi masalah tersebut:
Mungkin bisa dibuat lebih spesifik untuk menyingkirkan pengecualian lain.
sumber
Anda dapat melakukannya di file batch Anda dengan mengurai output dari:
lalu menjalankan
psql.exe
sekali lagi jika peran tersebut tidak ada.sumber
Solusi yang sama seperti untuk Simulasikan BUAT DATABASE JIKA TIDAK ADA untuk PostgreSQL? harus bekerja - kirim
CREATE USER …
ke\gexec
.Solusi dari dalam psql
Solusi dari shell
Lihat jawaban yang diterima di sana untuk lebih jelasnya.
sumber