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:
EXECUTEmenghasilkanGRANT. yang sesuai pada setiap doa menggunakan argumen prosedur kami. Bagian manual PG yang disebut "Melaksanakan Perintah Dinamis " menjelaskanEXECUTEsecara rinci.- Deklarasi argumen prosedur
userharus 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!