Trả lời
DO
mong đợi một chuỗi ký tự với mã plpgsql. Các ký hiệu không được thay thế bên trong chuỗi trong psql.
Bạn có thể nối toàn bộ chuỗi vào một biến psql và sau đó thực thi nó.
- Cách nối các biến psql?
Định dạng nhiều dòng khá không thể thực hiện được, bởi vì (theo tài liệu):
Nhưng trong mọi trường hợp, các đối số của lệnh meta không thể tiếp tục sau khi kết thúc dòng.
Ví dụ đơn giản:
test=# \set value foo
test=# \set do 'BEGIN\n RAISE NOTICE ''v: %'', ' :'value' ';\nEND'
test=# DO :'do';
NOTICE: v: foo
Thay thế ngắt dòng bằng \n
(hoặc loại bỏ chúng nếu bạn không quan tâm đến định dạng đẹp). Dựa trên mã điều chỉnh này:
DO
'
DECLARE
_val text;
_vals text[] := string_to_array(>>values<<, '','');
BEGIN
FOREACH _val IN ARRAY _vals
LOOP
RAISE NOTICE ''v: %'', _val;
END LOOP;
END
'
Nó trông như thế này:
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
Tôi đã thêm in đậm nhấn mạnh vào biến để dễ phát hiện hơn.
Câu trả lời liên quan của @Pavel (ab) sử dụng biến phiên máy chủ:
- Tham chiếu đến các biến phiên (\ set var ='value') từ PL / PGSQL
Các giải pháp thay thế
Báo cáo soạn sẵn
Giải pháp hiện tại của bạn trông không tệ như vậy. Tôi sẽ đơn giản hóa:
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$;
Bảng tạm thời
Giải pháp tương tự với bảng tạm thời:
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$;