Jawab
DO
mengharapkan string literal dengan kode plpgsql. Simbol tidak diganti di dalam string di psql.
Anda dapat menggabungkan seluruh string menjadi variabel psql dan lalu jalankan.
- Bagaimana cara menggabungkan variabel psql?
Format multi-baris yang cantik tidak dimungkinkan, karena (per dokumentasi):
Namun bagaimanapun juga, argumen dari meta-command tidak dapat dilanjutkan di luar akhir baris.
Contoh sederhana:
test=# \set value foo
test=# \set do 'BEGIN\n RAISE NOTICE ''v: %'', ' :'value' ';\nEND'
test=# DO :'do';
NOTICE: v: foo
Ganti jeda baris dengan \n
(atau hapus jika Anda tidak peduli dengan format yang cantik). Berdasarkan kode yang diadaptasi ini:
DO
'
DECLARE
_val text;
_vals text[] := string_to_array(>>values<<, '','');
BEGIN
FOREACH _val IN ARRAY _vals
LOOP
RAISE NOTICE ''v: %'', _val;
END LOOP;
END
'
Tampilannya seperti ini:
test=# \set do 'DECLARE\n _val text;\n _vals text[] := string_to_array(' :'values' ', '','');\nBEGIN\n FOREACH _val IN ARRAY _vals\n LOOP\n RAISE NOTICE ''v: %'', _val;\n END LOOP;\nEND'
test=# DO :'do';
NOTICE: v: foo
NOTICE: v: bar
NOTICE: v: baz
DO
Saya menambahkan tebal penekanan pada variabel agar lebih mudah dikenali.
Jawaban terkait oleh @Pavel (ab)menggunakan variabel sesi server:
- Merujuk ke variabel sesi (\set var='value') dari PL/PGSQL
Solusi alternatif
Pernyataan yang disiapkan
Solusi Anda saat ini tidak terlihat buruk. Saya akan menyederhanakan:
PREPARE get_values AS SELECT * FROM regexp_split_to_table(:'values', ',');
DO
$do$
DECLARE
_val text;
BEGIN
FOR _val IN EXECUTE
'EXECUTE get_values'
LOOP
RAISE NOTICE 'v: %', _val;
END LOOP;
END
$do$;
Tabel sementara
Solusi serupa dengan tabel sementara:
CREATE TEMP TABLE tmp AS SELECT * FROM regexp_split_to_table(:'values', ',') v;
DO
$do$
DECLARE
_val text;
BEGIN
FOR _val IN
TABLE tmp
LOOP
RAISE NOTICE 'v: %', _val;
END LOOP;
END
$do$;