Psql'ye argümanlar iletme


10

Postgres 8.3 bir plpgsql komut dosyası çalıştırıyorum - psql aracılığıyla bu komut dosyasına argümanlar geçirmek istiyorum. Şu anda komut dosyasını şu şekilde yürütüyorum:

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

PGOPTIONS ortam değişkenini açıklayan ancak "özel" bağımsız değişkenler için çalışmayan bu bağlantıyla karşılaştım . yani ayar postgres.conf dosyasında listelenmediği için bir hata alıyorum.

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

Başka fikir var mı? İdeal olarak ortam değişkenlerinden kaçınmak istiyorum ...


Bence -vpsql argümanını arıyorsunuz .
dezso

Bunu denedim - kodda almak için, "SELECT current_setting ('pretend') INTO _result" - başarı yok.
Jmoney38

Yanıtlar:


5

Açıkçası, "plpgsql betiği" diye bir şey yoktur - PL / pgSQL, PostgreSQL'in varsayılan yordamsal dilidir. Bu bir SQL betiği veya bir plpgsql işlevi / yordamıdır. Örneğiniz bir SQL komut dosyasını gösteriyor gibi görünüyor.

Bunun yerine, herhangi bir sayıda bağımsız değişken alan bir (sunucu tarafı) plpgsql (veya sql) işlevi oluşturabilirsiniz. Argümanlar olduğu sürece çok basit values. Bağımsız değişkenler tanımlayıcılar içeriyorsa biraz daha karmaşık hale gelir. Ardından dinamik SQL ve ile PL / pgSQL kullanmanız gerekir EXECUTE.

PL / pgSQL, PostgreSQL 9.0 veya sonraki sürümlerinde varsayılan olarak önceden yüklenmiştir. Yine de, Postgres 8.3'te veritabanı başına bir kez yüklemeniz gerekir:

CREATE LANGUGAGE plpgsql;

Sürümden bahsetmişken: PostgreSQL'in güncel bir sürümüne geçmeyi düşünmelisiniz . v8.3 şimdiye kadar çok eskidir, 2013'ün başlarında kullanım ömrü dolmuştur.

Hazır bir SQL betiğine sahip olduğunuz için bir SQL işlevi göstereceğim. İki tamsayı bağımsız değişkeni ile basit kukla işlev:

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

Sen plpgsql için daha birçok gelişmiş örnek bulabilirsiniz Burada dba.SE üzerinde veya benzeri .

Bu işlevi çağırabilir ve bir kabuk komut dosyasındaki parametreleri verebilirsiniz: Tam sayı parametreleri için giriş parametreleri kullanan bir kabuk komut dosyasındaki çağrı için temel örnek (değerin etrafında tek tırnak gerekmez):

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

Veya herhangi bir veri türüyle:

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

-cbir komut dizesi yürütür ve sonra çıkar. Kılavuzdaki psql komut satırı bağımsız değişkenleri hakkında daha fazla bilgi .


Yanıt için teşekkürler - Aslında oldukça plpgsql farkındayım - Bahsettiğim bu komut dosyası çok sayıda işlev içeren bir dosyadır. C-yönelimli programlama anlamında bir "ana" fonksiyonum var. Komut dosyası / dosyadaki son 2 satır 1) "ana" işlevi çağırır ve sonra 2) işlevi bırakır. Yani, bu kurulumda, aslında iş yapmak için çalıştırılabilir bağımsız bir komut dosyası var (psql -f). Ben psql -c aracılığıyla "uygulama argüman" ile bir fonksiyon çağırma hakkında görüşünü seviyorum. Muhtemelen bu yolu seçeceğim, çünkü postgres.conf dosyasına değer ekleme yoluna gidemiyorum.
Jmoney38

5

İçin başka bir işlevsellik eklemek için -v... Teklifi eklemeye çalışıyorsanız, bunu komut satırına ekleyin:

psql -v action="'drop'"

ve bu kodun çalışmasını sağlar:

select * where :action;

Aynı

select * where 'drop';

4

Deneyin -v:

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

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

Kullanmak istiyorsanız current_settingve SETveya setval, postgresql.confseçeneği eklemek için bir satır eklemeniz gerekir.


2

Deneyimlerime göre, CREATE FUNCTION BEGIN veya DO BEGIN gibi bir plpgsql bildirimi içinde bir psql değişkeninin kaydının kaldırılması bir sözdizimi hatasıyla sonuçlanır:

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

Benim çözümüm, tek bir sütun ile geçici bir tablo oluşturmak ve değeri içinde saklamaktır. Bu geçici tablo plpgsql üzerinden erişilebilir ve bu nedenle DO bloklarında kullanılan psql değişkenlerini iletebilirim.

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

CREATE FUNCTION veya DO bildirimlerinde ek psql değişkenleri kullanmak için, gereken değişken başına bir sütun oluşturabilirsiniz.


0

Bu çok zarif değil ama işe yarıyor (sözde kod):

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

0

Bu yaklaşım, env değişkenlerinin tam çalışma zamanı çözünürlüğünü sağlayacaktır ... böylece komut dosyanız önceden çalıştığında tüm kabuk değişkenlerini çalıştırır ( farklı dbs ve ana bilgisayarlara karşı binlerce kez çalıştırılmıştır ):

    -- 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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.