Truyền đối số cho psql


10

Tôi đang chạy tập lệnh plpgsql trong Postgres 8.3 - Tôi muốn chuyển các đối số cho tập lệnh này thông qua psql. Tôi hiện đang thực thi kịch bản như:

psql -d database -u user -f update_file.sql 

Tôi đã xem qua liên kết này giải thích biến môi trường PGOPTIONS, nhưng nó không hoạt động cho các đối số "tùy chỉnh". tức là tôi nhận được lỗi vì cài đặt không được liệt kê trong tệp postgres.conf.

-bash-3.2$ export PGOPTIONS='--pretend=true'
-bash-3.2$ psql -d my_db -f update_database.sql
psql: FATAL:  unrecognized configuration parameter "pretend"

Còn ý tưởng nào khác không? Lý tưởng nhất là tôi muốn tránh các biến môi trường ...


Tôi nghĩ rằng bạn đang tìm kiếm -vđối số của psql.
dezso

Tôi đã thử điều đó - để lấy nó trong tập lệnh, tôi đang gọi "CHỌN current_setting ('giả vờ') VÀO _result" - không thành công.
Jmoney38

Câu trả lời:


5

Nói một cách chính xác, không có thứ gọi là "tập lệnh plpgsql" - PL / pgQuery là ngôn ngữ thủ tục mặc định của PostgreQuery. Đó là tập lệnh SQL hoặc hàm / thủ tục plpgsql. Ví dụ của bạn dường như chỉ ra một tập lệnh SQL.

Thay vào đó, bạn có thể tạo một hàm plpgsql (hoặc sql) ( phía máy chủ ) , có bất kỳ số lượng đối số nào. Nó rất đơn giản miễn là các đối số values. Sẽ phức tạp hơn một chút nếu các đối số bao gồm các định danh. Sau đó, bạn sẽ phải sử dụng PL / pgQuery với SQL động và EXECUTE.

PL / pgSQL được cài đặt sẵn theo mặc định trong PostgreSQL 9.0 trở lên. Bạn phải cài đặt nó một lần cho mỗi cơ sở dữ liệu trong Postgres 8.3, mặc dù:

CREATE LANGUGAGE plpgsql;

Nói về phiên bản: bạn nên xem xét nâng cấp lên phiên bản hiện tại của PostgreSQL. v8.3 đã rất cũ, đến cuối năm 2013.

Vì dường như bạn đã có một tập lệnh SQL sẵn sàng, tôi sẽ trình bày một hàm SQL. Hàm giả đơn giản với hai đối số nguyên:

CREATE OR REPLACE FUNCTION func(int, int)
    LANGUAGE sql RETURNS void AS 
$func$
    UPDATE tbl1 SET col1 = $1 WHERE id = $2;
    UPDATE tbl2 SET col1 = $1 WHERE id = $2;
$func$;

Bạn có thể tìm thấy nhiều ví dụ phức tạp hơn cho plpgsql tại đây trên dba.SE hoặc trên SO .

Bạn có thể gọi hàm này và đưa các tham số vào tập lệnh shell: Ví dụ cơ bản cho cuộc gọi trong tập lệnh shell sử dụng tham số đầu vào cho tham số nguyên (không có dấu ngoặc đơn xung quanh giá trị cần thiết):

psql mydb -c "SELECT func($1, $2)"

Hoặc với bất kỳ loại dữ liệu:

psql mydb -c "SELECT func2('$1'::text, '$2'::numeric)"

-cthực thi một chuỗi lệnh và sau đó thoát. Thông tin thêm về các đối số dòng lệnh của psql trong hướng dẫn .


Cảm ơn bạn đã phản hồi - Tôi thực sự khá biết về plpgsql - Tập lệnh này tôi đang đề cập đến là một tệp có chứa nhiều chức năng. Tôi có một chức năng "chính" theo nghĩa lập trình hướng C. 2 dòng cuối cùng trong tập lệnh / tập tin là 1) gọi hàm "chính" và sau đó 2) bỏ chức năng. Vì vậy, trong thiết lập này, về cơ bản, tôi có một tập lệnh độc lập có thể chạy để thực hiện công việc (psql -f). Tôi thích quan điểm của bạn về việc gọi một hàm với "application args" thông qua psql -c. Có lẽ tôi sẽ đi theo con đường đó, vì tôi không thể đi theo con đường thêm giá trị vào tệp postgres.conf.
Jmoney38

5

Để thêm chức năng khác cho -v... Nếu bạn đang cố thêm trích dẫn, hãy thêm nó vào dòng lệnh:

psql -v action="'drop'"

và điều này sẽ chạy mã cho:

select * where :action;

Giống như

select * where 'drop';

4

Hãy thử -v:

$ psql -U postgres -v something=\'blah-blah\'
psql (9.1.3)
Type "help" for help.

postgres=# select :something;
 ?column?
----------
 blah-blah
(1 row)

Nếu bạn muốn sử dụng current_settingSEThoặc setval, bạn phải nối một hàng postgresql.confđể thêm tùy chọn.


2

Từ kinh nghiệm của tôi, việc hủy bỏ một biến psql bên trong một khai báo plpgsql, chẳng hạn như trong CREATE FUNCTION BEGIN hoặc DO BEGIN dẫn đến lỗi cú pháp:

/tmp $ psql -U jmindek -v action=drop
psql (9.3.4)
Type "help" for help.

jmindek=# select :'action';
 ?column? 
----------
 drop
(1 row)

jmindek=# DO $$ BEGIN RAISE INFO 'The value in variable action is (%)',:x; END $$;     
ERROR:  syntax error at or near ":"
LINE 1: ... RAISE INFO 'The value in variable action is (%)',:x; END $$...

Giải pháp của tôi là tạo một bảng tạm thời với một cột duy nhất và lưu trữ giá trị trong đó. Bảng tạm thời này có thể truy cập thông qua plpgsql và do đó tôi có thể chuyển các biến psql được sử dụng trong các khối DO.

 ~ $ psql -v action=drop
psql (9.3.4)
Type "help" for help.

jmindek=# create temporary table actions (type text);                                                             CREATE TABLE
jmindek=# insert into actions values (:'action');                                                                 INSERT 0 1
jmindek=# do $$                                                                                                   declare                                                                                                            action_type text := null;                                                                                        begin                                                                                                               select type from actions into action_type;                                                                        raise info 'Hello, the action is (%)',action_type;                                                              end $$;
INFO:  Hello, the action is (drop)
DO
jmindek=#

Để sử dụng các biến psql bổ sung trong khai báo CREATE FUNCTION hoặc DO, bạn có thể tạo một cột cho mỗi biến cần thiết.


0

Điều này không phải là rất thanh lịch nhưng nó hoạt động (mã giả):

cat <<EOF
   UPDATE tablename SET field=$arg1 WHERE field = $arg2;
EOF | psql database

0

Cách tiếp cận này sẽ cung cấp cho bạn độ phân giải toàn thời gian của các env vars ... vì vậy ngay khi tập lệnh của bạn đặt trước tất cả các biến shell bên dưới, nó sẽ hoạt động ( đã được chạy hàng ngàn lần so với các dbs và máy chủ khác nhau ):

    -- start run.sh

       # 01 create / modify the app user
       sql_script="$pgsql_scripts_dir/01.create-qto-app-user.pgsql"
       PGPASSWORD="${postgres_db_useradmin_pw:-}" psql -q -t -X -w -U "${postgres_db_useradmin:-}" \
          -h $postgres_db_host -p $postgres_db_port \
          -v ON_ERROR_STOP=1 \
          -v postgres_db_user_pw="${postgres_db_user_pw:-}" \
          -v postgres_db_name="${postgres_db_name:-}" \
          -f "$sql_script" "${postgres_db_name:-}" > "$tmp_log_file" 2>&1
       ret=$?
       cat "$tmp_log_file" ; cat "$tmp_log_file" >> $log_file # show it and save it
       test $ret -ne 0 && sleep 3
       test $ret -ne 0 && doExit 1 "pid: $$ psql ret $ret - failed to run sql_script: $sql_script !!!"
    -- stop run.sh

    -- start fun.sql
            DO
            $do$
            BEGIN
               IF NOT EXISTS (
                  SELECT
                  FROM   pg_catalog.pg_roles
                  WHERE  rolname = 'usrqtoapp') THEN
                     CREATE ROLE usrqtoapp WITH PASSWORD ':postgres_db_user_pw' LOGIN ;
               END IF;
            END
            $do$;
            ALTER ROLE usrqtoapp WITH PASSWORD  :'postgres_db_user_pw' LOGIN ;

    -- eof run.sql
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.