Передача аргументів psql


10

Я запускаю скрипт plpgsql у Postgres 8.3 - я хотів би передати аргументи цьому сценарію через psql. Наразі виконую сценарій, наприклад:

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

Я натрапив на це посилання, яке пояснює змінну середовища PGOPTIONS, але це не працює для "спеціальних" аргументів. тобто я отримую помилку, оскільки параметр не вказаний у файлі 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"

Будь-які інші ідеї? В ідеалі я хотів би уникати змінних середовищ ...


Я думаю, ви шукаєте -vаргумент psql.
dezso

Я спробував це - щоб отримати його в сценарії, я називаю "SELECT current_setting ('прикидатися") INTO _result "- успіху немає.
Jmoney38

Відповіді:


5

Строго кажучи, немає такого поняття, як "скрипт plpgsql" - PL / pgSQL є мовою процедур за замовчуванням PostgreSQL. Це або сценарій SQL, або функція / процедура plpgsql. Схоже, ваш приклад вказує на сценарій SQL.

Ви можете створити функцію plpgsql (або sql) на стороні сервера , яка приймає будь-яку кількість аргументів. Це дуже просто, доки є аргументи values. Це стає трохи складніше, якщо аргументи включають ідентифікатори. Тоді вам доведеться використовувати PL / pgSQL з динамічним SQL і EXECUTE.

PL / pgSQL попередньо встановлено за замовчуванням у PostgreSQL 9.0 або новіших версіях. Ви повинні встановити його один раз у базі даних у Postgres 8.3, однак:

CREATE LANGUGAGE plpgsql;

Якщо говорити про версію: вам слід розглянути можливість оновлення до поточної версії PostgreSQL. v8.3 вже дуже старий, на кінець життя на початку 2013 року.

Оскільки у вас, здається, є готовий сценарій SQL, я продемонструю функцію SQL. Проста фіктивна функція з двома цілими аргументами:

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$;

Ви можете знайти ще багато складних прикладів для plpgsql тут на dba.SE або на SO .

Ви можете викликати цю функцію та ввести параметри в сценарії оболонки: Основний приклад для виклику в скрипті оболонки, який використовує вхідні параметри для цілих параметрів (жодних лапок навколо значення не потрібно):

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

Або з будь-яким типом даних:

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

-cвиконує один командний рядок, а потім виходить. Детальніше про аргументи командного рядка psql в посібнику .


Дякую за відповідь - я насправді цілком обізнаний з plpgsql - Цей скрипт, про який я звертаюся, - це файл, який містить численні функції. У мене є "основна" функція в розумінні програмування, орієнтованого на С. Останні 2 рядки в скрипті / файлі - це 1) виклик "головної" функції, а потім 2) відміна функції. Отже, у цій установці я, по суті, маю автономний сценарій, який можна запустити для виконання роботи (psql -f). Мені подобається ваша думка щодо виклику функції за допомогою "аргументів програми" через psql -c. Я, мабуть, пройду цей маршрут, тому що я не можу пройти маршрут додавання значень у файл postgres.conf.
Jmoney38

5

Щоб додати ще одну функціональність для -v... Якщо ви намагаєтесь додати пропозицію, додайте її в командному рядку:

psql -v action="'drop'"

і це запустить код для:

select * where :action;

Такий же як і

select * where 'drop';

4

Спробуйте -v:

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

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

Якщо ви хочете використовувати current_settingта SETабо setval, вам потрібно додати рядок, postgresql.confщоб додати опцію.


2

З мого досвіду, відновлення змінної psql всередині декларації plpgsql, наприклад у CREATE FUNCTION BEGIN або DO BEGIN, призводить до помилки синтаксису:

/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 $$...

Моє рішення - створити тимчасову таблицю з одним стовпцем і зберегти в ній значення. Ця тимчасова таблиця доступна через plpgsql, і тому я можу передавати змінні psql, використовувані в блоках 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=#

Щоб використовувати додаткові змінні psql у деклараціях CREATE FUNCTION або DO, ви можете створити стовпчик для потрібної змінної.


0

Це не дуже елегантно, але це працює (псевдокод):

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

0

Такий підхід забезпечить вам повне дозвіл часу env vars ... так що, як тільки ваш сценарій встановить заздалегідь всі змінні оболонки внизу, він буде працювати ( тисячі разів був застосований проти різних dbs та хостів ):

    -- 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.