it-swarm-eu.dev

Předávání argumentů psql

Používám skript plpgsql v Postgresu 8.3 - Chtěl bych do tohoto skriptu předat argumenty pomocí psql. Momentálně spouštím skript jako:

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

Narazil jsem na Tento odkaz , který vysvětluje proměnnou prostředí PGOPTIONS, ale to nefunguje pro "vlastní" argumenty. tj. zobrazí se chyba, protože nastavení není uvedeno v souboru 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"

Máte nějaké další nápady? V ideálním případě bych se chtěl vyhnout proměnným prostředí ...

10
Jmoney38

Přísně vzato neexistuje nic jako „skript plpgsql“ - PL/pgSQL je výchozí procedurální jazyk PostgreSQL. Je to buď skript SQL nebo plpgsql funkce/procedura. Zdá se, že váš příklad naznačuje skript SQL.

Místo toho můžete vytvořit funkci plpgsql (nebo sql) na straně serveru, která vezme libovolný počet argumentů. Je to velmi jednoduché, pokud jsou argumenty values. Pokud argumenty obsahují identifikátory, je to trochu složitější. Pak budete muset použít PL/pgSQL s dynamickým SQL a EXECUTE .

PL/pgSQL je standardně předinstalován v PostgreSQL 9.0 nebo novější. Musíte ji nainstalovat jednou pro každou databázi v Postgres 8.3, i když:

CREATE LANGUGAGE plpgsql;

Když už mluvíme o verzi: měli byste zvažte upgrade na současnou verzi PostgreSQL. v8.3 je nyní velmi starý, konec životnosti na začátku roku 2013.

Protože se zdá, že máte připravený skript SQL, ukážu funkci SQL. Jednoduchá fiktivní funkce se dvěma celočíselnými argumenty:

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

Najdete mnoho sofistikovanějších příkladů pro plpgsql zde na dba.SE nebo na SO .

Tuto funkci můžete zavolat a předat parametry ve skriptu Shell: Základní příklad volání ve skriptu Shell, který používá vstupní parametry pro celočíselné parametry (bez uvozovek kolem potřebné hodnoty):

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

Nebo s jakýmkoli typem dat:

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

-c provede jeden příkazový řetězec a poté skončí. Více o argumentech příkazového řádku psql v manuál .

5

Chcete-li přidat další funkci pro -v... Pokud se pokoušíte přidat nabídku, přidejte ji do příkazového řádku:

psql -v action="'drop'"

a tím se spustí kód pro:

select * where :action;

Stejný jako

select * where 'drop';
5
cline

Snaž se -v:

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

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

Pokud chcete použít current_setting a SET nebo setval, musíte připojit řádek k postgresql.conf pro přidání možnosti.

4
dezso

Z mé zkušenosti vyplývá, že dereffing psql proměnné uvnitř deklarace plpgsql, například v CREATE FUNCTION BEGIN nebo DO BEGIN, vede k chybě syntaxe:

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

Mým řešením je vytvořit dočasnou tabulku s jedním sloupcem a do ní uložit hodnotu. Tato dočasná tabulka je přístupná pomocí plpgsql, a tak mohu předávat proměnné psql používané v blocích 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=#

Chcete-li použít další proměnné psql v CREATE FUNCTION nebo DO prohlášení, můžete vytvořit sloupec pro každou potřebnou proměnnou.

2
Jerry Mindek

Není to moc elegantní, ale funguje to (pseudokód):

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

Tento přístup vám poskytne plné běhové rozlišení env vars ... takže jakmile váš skript nastaví předem všechny proměnné Shell níže, bude to fungovat ( byl spuštěn tisícekrát proti různým dbs) a hostitelé ):

    -- 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
0
Yordan Georgiev