Argumente an psql übergeben


10

Ich führe ein plpgsql-Skript in Postgres 8.3 aus - Ich möchte Argumente über psql an dieses Skript übergeben. Ich führe das Skript derzeit wie folgt aus:

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

Ich bin auf diesen Link gestoßen, der die Umgebungsvariable PGOPTIONS erklärt, aber für "benutzerdefinierte" Argumente nicht funktioniert. dh ich erhalte eine Fehlermeldung, weil die Einstellung nicht in der Datei postgres.conf aufgeführt ist.

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

Irgendwelche anderen Ideen? Idealerweise möchte ich Umgebungsvariablen vermeiden ...


Ich denke, Sie suchen nach dem -vArgument von psql.
Dekso

Ich habe das versucht - um es im Skript abzurufen, rufe ich "SELECT current_setting ('pretend') INTO _result" auf - kein Erfolg.
Jmoney38

Antworten:


5

Genau genommen gibt es kein "plpgsql-Skript" - PL / pgSQL ist die Standardprozedursprache von PostgreSQL. Es ist entweder ein SQL-Skript oder eine plpgsql-Funktion / Prozedur. Ihr Beispiel scheint auf ein SQL-Skript hinzuweisen.

Sie können stattdessen eine (serverseitige ) Funktion plpgsql (oder sql) erstellen , die eine beliebige Anzahl von Argumenten akzeptiert . Es ist sehr einfach, solange die Argumente sind values. Es wird etwas komplizierter, wenn die Argumente Bezeichner enthalten. Dann müssen Sie PL / pgSQL mit dynamischem SQL und verwenden EXECUTE.

PL / pgSQL ist in PostgreSQL 9.0 oder höher standardmäßig vorinstalliert. Sie müssen es jedoch einmal pro Datenbank in Postgres 8.3 installieren:

CREATE LANGUGAGE plpgsql;

Apropos Version: Sie sollten ein Upgrade auf eine aktuelle Version von PostgreSQL in Betracht ziehen . v8.3 ist mittlerweile sehr alt und endet Anfang 2013.

Da Sie anscheinend ein fertiges SQL-Skript haben, werde ich eine SQL-Funktion demonstrieren. Einfache Dummy-Funktion mit zwei ganzzahligen Argumenten:

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

Viele anspruchsvollere Beispiele für plpgsql finden Sie hier auf dba.SE oder auf SO .

Sie können diese Funktion aufrufen und Parameter in einem Shell-Skript übergeben: Grundlegendes Beispiel für einen Aufruf in einem Shell-Skript, das Eingabeparameter für ganzzahlige Parameter verwendet (keine einfachen Anführungszeichen um den erforderlichen Wert):

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

Oder mit einem beliebigen Datentyp:

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

-cführt eine Befehlszeichenfolge aus und wird dann beendet. Weitere Informationen zu Befehlszeilenargumenten von psql finden Sie im Handbuch .


Vielen Dank für die Antwort - ich bin mir plpgsql eigentlich ziemlich bewusst - Dieses Skript, auf das ich mich beziehe, ist eine Datei, die zahlreiche Funktionen enthält. Ich habe eine "Haupt" -Funktion im Sinne einer C-orientierten Programmierung. Die letzten 2 Zeilen innerhalb des Skripts / der Datei lauten 1) Aufrufen der "Haupt" -Funktion und 2) Löschen der Funktion. In diesem Setup habe ich also im Wesentlichen ein in sich geschlossenes Skript, das ausgeführt werden kann, um Arbeit zu leisten (psql -f). Ich mag Ihren Punkt über das Aufrufen einer Funktion mit den "Anwendungsargumenten" über psql -c. Ich werde diesen Weg wahrscheinlich gehen, weil ich den Weg des Hinzufügens von Werten zur Datei postgres.conf nicht gehen kann.
Jmoney38

5

So fügen Sie eine weitere Funktionalität hinzu für -v... Wenn Sie versuchen, das Angebot hinzuzufügen, fügen Sie es in der Befehlszeile hinzu:

psql -v action="'drop'"

und dies wird den Code ausführen für:

select * where :action;

Das Gleiche wie

select * where 'drop';

4

Versuchen Sie -v:

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

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

Wenn Sie current_settingund SEToder verwenden möchten setval, müssen Sie eine Zeile anhängen postgresql.conf, um die Option hinzuzufügen.


2

Nach meiner Erfahrung führt das Dereffing einer psql-Variablen in einer plpgsql-Deklaration wie in CREATE FUNCTION BEGIN oder DO BEGIN zu einem Syntaxfehler:

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

Meine Lösung besteht darin, eine temporäre Tabelle mit einer einzelnen Spalte zu erstellen und den Wert darin zu speichern. Auf diese temporäre Tabelle kann über plpgsql zugegriffen werden, sodass ich psql-Variablen übergeben kann, die in DO-Blöcken verwendet werden.

 ~ $ 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=#

Um zusätzliche psql-Variablen in CREATE FUNCTION- oder DO-Deklarationen zu verwenden, können Sie eine Spalte pro benötigter Variable erstellen.


0

Das ist nicht sehr elegant, aber es funktioniert (Pseudocode):

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

0

Mit diesem Ansatz erhalten Sie eine vollständige Laufzeitauflösung der env-Variablen. Sobald Ihr Skript alle unten aufgeführten Shell-Variablen vorab festgelegt hat, funktioniert es ( wurde tausende Male gegen verschiedene Datenbank- und Hosts ausgeführt ):

    -- 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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.