Passando argomenti a psql


10

Sto eseguendo uno script plpgsql in Postgres 8.3 - Vorrei passare argomenti a questo script tramite psql. Attualmente sto eseguendo lo script come:

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

Mi sono imbattuto in questo link che spiega la variabile d'ambiente PGOPTIONS, ma che non funziona per argomenti "personalizzati". cioè ricevo un errore perché l'impostazione non è elencata nel file 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"

Altre idee? Idealmente, vorrei evitare le variabili di ambiente ...


Penso che tu stia cercando l' -vargomento di psql.
dezso

Ho provato questo - per recuperarlo nello script, sto chiamando "SELECT current_setting ('pretend') INTO _result" - nessun successo.
Jmoney38,

Risposte:


5

A rigor di termini, non esiste un "script plpgsql": PL / pgSQL è il linguaggio procedurale predefinito di PostgreSQL. È uno script SQL o una funzione / procedura plpgsql. Il tuo esempio sembra indicare uno script SQL.

È possibile invece creare una funzione plpgsql (o sql) ( lato server) che accetta un numero qualsiasi di argomenti. È molto semplice purché gli argomenti lo siano values. Diventa un po 'più complicato se gli argomenti includono identificatori. Quindi dovrai usare PL / pgSQL con SQL dinamico e EXECUTE.

PL / pgSQL è preinstallato di default in PostgreSQL 9.0 o versioni successive. Devi installarlo una volta per database in Postgres 8.3, però:

CREATE LANGUGAGE plpgsql;

A proposito della versione: dovresti prendere in considerazione l'aggiornamento a una versione corrente di PostgreSQL. v8.3 è ormai molto vecchio, fine vita all'inizio del 2013.

Dato che sembri avere uno script SQL pronto, ti mostrerò una funzione SQL. Funzione fittizia semplice con due argomenti interi:

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

Puoi trovare molti esempi più sofisticati per plpgsql qui su dba.SE o su SO .

È possibile chiamare questa funzione e consegnare i parametri in uno script di shell: Esempio di base per una chiamata in uno script di shell che utilizza parametri di input per parametri interi (senza virgolette singole attorno al valore necessario):

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

O con qualsiasi tipo di dati:

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

-cesegue una stringa di comando e quindi esce. Maggiori informazioni sugli argomenti della riga di comando di psql nel manuale .


Grazie per la risposta - In realtà sono abbastanza consapevole di plpgsql - Questo script a cui mi riferisco è un file che contiene numerose funzioni. Ho una funzione "principale" nel senso della programmazione orientata al C. Le ultime 2 righe all'interno dello script / file sono 1) chiamando la funzione "principale" e quindi 2) rilasciando la funzione. Quindi, in questa configurazione, ho essenzialmente uno script autonomo che può essere eseguito per funzionare (psql -f). Mi piace il tuo punto di chiamare una funzione con "args applicazione" tramite psql -c. Probabilmente seguirò quella strada, perché non riesco a seguire la strada dell'aggiunta di valori al file postgres.conf.
Jmoney38,

5

Per aggiungere un'altra funzionalità per -v... Se stai provando ad aggiungere l'offerta, aggiungila nella riga di comando:

psql -v action="'drop'"

e questo eseguirà il codice per:

select * where :action;

Lo stesso di

select * where 'drop';

4

Prova -v:

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

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

Se si desidera utilizzare current_settinge SETo setval, è necessario aggiungere una riga postgresql.confper aggiungere l'opzione.


2

Dalla mia esperienza, eliminare una variabile psql all'interno di una dichiarazione plpgsql come in CREATE FUNCTION BEGIN o DO BEGIN provoca un errore di sintassi:

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

La mia soluzione è quella di creare una tabella temporanea con una singola colonna e memorizzare il valore in essa. Questa tabella temporanea è accessibile tramite plpgsql e quindi posso passare le variabili psql utilizzate con nei blocchi 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=#

Per utilizzare ulteriori variabili psql nelle dichiarazioni CREATE FUNCTION o DO, è possibile creare una colonna per variabile necessaria.


0

Questo non è molto elegante ma funziona (pseudocodice):

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

0

Questo approccio ti fornirà la piena risoluzione di runtime dei vari ambienti ... quindi non appena lo script imposterà in anticipo tutte le variabili di shell seguenti funzionerà ( è stato eseguito migliaia di volte contro diversi dbs e host ):

    -- 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.