PSQL SET
variabel tidak diinterpolasi di dalam string yang dikutip dolar. Saya tidak tahu pasti, tapi saya pikir tidak ada jalan keluar atau tipu daya lain untuk mengaktifkan SET
interpolasi variabel di sana.
Orang mungkin berpikir Anda dapat memasang :user
yang tidak dikutip antara dua bentangan PL/pgSQL yang dikutip dolar untuk mendapatkan efek yang diinginkan. Tapi ini sepertinya tidak berhasil... Saya pikir sintaksnya membutuhkan string tunggal dan bukan string yang menggabungkan ekspresi. Mungkin salah dalam hal itu.
Bagaimanapun, itu tidak masalah. Ada pendekatan lain (seperti yang dicatat Pasco):tulis prosedur tersimpan untuk menerima argumen PL/pgSQL. Begini tampilannya.
CREATE OR REPLACE FUNCTION foo("user" TEXT) RETURNS void AS
$$
BEGIN
EXECUTE 'GRANT SELECT ON my_table TO GROUP ' || quote_ident(user);
END;
$$ LANGUAGE plpgsql;
Catatan tentang fungsi ini:
EXECUTE
menghasilkanGRANT
. yang sesuai pada setiap doa menggunakan argumen prosedur kami. Bagian manual PG yang disebut "Melaksanakan Perintah Dinamis " menjelaskanEXECUTE
secara rinci.- Deklarasi argumen prosedur
user
harus dikutip ganda. Tanda kutip ganda memaksanya untuk ditafsirkan sebagai pengenal.
Setelah Anda mendefinisikan fungsi seperti ini, Anda dapat memanggilnya menggunakan variabel PSQL yang diinterpolasi. Berikut garis besarnya.
- Jalankan
psql --variable user="'whoever'" --file=myscript.sql
. Kutipan tunggal diperlukan di sekitar nama pengguna! - Di myscript.sql, tentukan fungsi seperti di atas.
- Di myscript.sql, masukkan
select foo(:user);
. Di sinilah kami mengandalkan tanda kutip tunggal yang kami masukkan ke dalam nilaiuser
.
Meskipun ini tampaknya berhasil, menurut saya ini agak squirrely. Saya pikir SET
variabel dimaksudkan untuk konfigurasi runtime. Membawa data dalam SET
sepertinya aneh.
Sunting :inilah alasan konkret untuk tidak gunakan SET
variabel. Dari halaman manual:"Penugasan ini dilakukan selama tahap awal startup, jadi variabel yang dicadangkan untuk keperluan internal mungkin akan ditimpa nanti." Jika Postgres memutuskan untuk menggunakan variabel bernama user
(atau apa pun yang Anda pilih), itu bisa menimpa argumen skrip Anda dengan sesuatu yang tidak pernah Anda maksudkan. Sebenarnya, psql sudah mengambil USER
untuk dirinya sendiri -- ini hanya berfungsi karena SET
peka huruf besar/kecil. Ini hampir merusak segalanya sejak awal!