将参数传递给psql


10

我在Postgres 8.3中运行一个plpgsql脚本-我想通过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"

还有其他想法吗?理想情况下,我想避免环境变量...


我认为您正在寻找-vpsql 的参数。
dezso 2012年

我尝试过-在脚本中检索它,我正在调用“ SELECT current_setting('pretend')INTO _result“-没有成功。
Jmoney38 2012年

Answers:


5

严格来说,没有“ plpgsql脚本”之类的东西-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到现在已经很老了,在2013年初就已经寿终正寝了。

由于您似乎已经准备好了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$;

您可以在dba.SESO 找到plpgsql的许多更复杂的示例。

您可以调用此函数并在Shell脚本中上交参数:Shell脚本中的调用的基本示例,该调用使用输入参数作为整数参数(所需值周围没有单引号):

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

或任何数据类型:

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

-c执行一个命令字符串,然后退出。手册中有关psql命令行参数的更多信息。


感谢您的答复-我实际上非常了解plpgsql-我所指的这个脚本是一个包含许多功能的文件。就面向C的编程而言,我有一个“主要”功能。脚本/文件中的最后两行是1)调用“ main”函数,然后2)删除该函数。因此,在此设置中,我实际上具有一个可以运行以完成工作的自包含脚本(psql -f)。我喜欢您关于通过psql -c使用“应用程序args”调用函数的观点。我可能会走这条路线,因为我无法走将值添加到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_settingSETsetval,则必须在其后添加一行postgresql.conf以添加该选项。


2

根据我的经验,在plpgsql声明中(例如在CREATE FUNCTION BEGIN或DO BEGIN中)对psql变量进行derefing会导致语法错误:

/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访问此临时表,因此我可以传递在DO块中使用的psql变量。

 ~ $ 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或DO声明中使用其他psql变量,可以为每个所需变量创建一列。


0

这不是很优雅,但是可以(伪代码):

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

0

这种方法将为您提供env vars的完整运行时解析...因此,只要您的脚本预先设置了下面的所有shell变量,它将起作用(已经针对不同的数据库和主机运行了数千次):

    -- 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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.