การส่งผ่านอาร์กิวเมนต์ไปยัง 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 ('แกล้ง') เข้าสู่ _result" - ไม่สำเร็จ
Jmoney38

คำตอบ:


5

พูดอย่างเคร่งครัดไม่มีสิ่งเช่น "plpgsql script" - 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 เก่ามากในตอนนี้จนถึงสิ้นปี 2556

เนื่องจากคุณดูเหมือนจะมีสคริปต์ 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หรือในดังนั้น

คุณสามารถเรียกใช้ฟังก์ชันนี้และส่งพารามิเตอร์ในเชลล์สคริปต์: ตัวอย่างพื้นฐานสำหรับการโทรในเชลล์สคริปต์ที่ใช้พารามิเตอร์อินพุตสำหรับพารามิเตอร์จำนวนเต็ม (ไม่ต้องใส่เครื่องหมายคำพูดเดี่ยว ๆ รอบค่าที่ต้องการ):

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

หรือกับชนิดข้อมูลใด ๆ :

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

-cรันหนึ่งสตริงคำสั่งแล้วออก เพิ่มเติมเกี่ยวกับบรรทัดคำสั่งขัดแย้งของpsql ในคู่มือ


ขอบคุณสำหรับการตอบสนอง - ฉันค่อนข้างทราบจริง ๆ แล้วว่า plpgsql - สคริปต์ที่ฉันอ้างถึงนี้เป็นไฟล์ที่มีฟังก์ชั่นมากมาย ฉันมีฟังก์ชั่น "หลัก" ในแง่ของการเขียนโปรแกรม C-oriented 2 บรรทัดสุดท้ายในสคริปต์ / ไฟล์คือ 1) เรียกใช้ฟังก์ชัน "main" จากนั้น 2) วางฟังก์ชันลง ดังนั้นในการตั้งค่านี้ฉันมีสคริปต์ในตัวที่สามารถทำงานได้ (psql -f) ฉันชอบจุดของคุณเกี่ยวกับการเรียกใช้ฟังก์ชันด้วย "แอปพลิเคชัน args" ผ่าน 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 declarations คุณสามารถสร้างคอลัมน์ต่อตัวแปรที่จำเป็น


0

มันไม่ได้สวยงามมาก แต่มันใช้งานได้ (pseudocode):

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

0

วิธีการนี้จะช่วยให้คุณความละเอียดเต็มเวลาทำงานของ env จะ vars ... ดังนั้นทันทีที่ชุดสคริปต์ของคุณก่อนที่มือทุกตัวแปรเปลือกร้องมันจะทำงาน ( ได้รับนับพันวิ่งครั้งกับดีบีเอสที่แตกต่างกันและเจ้าภาพ ):

    -- 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.