PostgreSQL:如何从命令行传递参数?

时间:2011-09-12 14:24:58

标签: postgresql

我在使用?占位符的脚本中有一个详细的查询。我想直接从psql命令行(脚本外部)测试这个相同的查询。我想避免进入并用实际值替换所有?,而是在查询之后传递参数。

示例:

SELECT  * 
FROM    foobar
WHERE   foo = ?
   AND  bar = ?
    OR  baz = ?  ;

寻找类似的东西:

%> {select * from foobar where foo=? and bar=? or baz=? , 'foo','bar','baz' };

7 个答案:

答案 0 :(得分:142)

您可以使用-v construct例如

psql -v v1=12  -v v2="'Hello World'" -v v3="'2010-11-12'"

然后将sql中的变量称为:v1,:v2等

select * from table_1 where id = :v1;

请注意我们如何使用两个引号" '...' "

传递字符串/日期值

答案 1 :(得分:24)

在PostgreSQL中发现,你可以像脚本语言一样PREPARE statements。很遗憾,您仍然无法使用?,但可以使用$n表示法。

使用上面的例子:

PREPARE foo(text,text,text) AS
    SELECT  * 
    FROM    foobar
    WHERE   foo = $1
       AND  bar = $2
        OR  baz = $3  ;
EXECUTE foo('foo','bar','baz');
DEALLOCATE foo;

答案 2 :(得分:10)

在psql中有一个通过

的机制
\set name val

命令,应该绑定到-v name=val命令行选项。引用很痛苦。在大多数情况下,将整个查询内容放在shell文件中更容易。

修改

oops,我应该说-v而不是-P(这是格式化选项)之前的回复是正确的。

答案 3 :(得分:5)

您还可以在psql命令行或批处理文件中传递参数。第一个语句收集连接到数据库的必要详细信息。

最后一个提示要求输入约束值,这些值将在WHERE列IN()子句中使用。请记住单引号if字符串,并用逗号分隔:

@echo off
echo "Test for Passing Params to PGSQL"
SET server=localhost
SET /P server="Server [%server%]: "

SET database=amedatamodel
SET /P database="Database [%database%]: "

SET port=5432
SET /P port="Port [%port%]: "

SET username=postgres
SET /P username="Username [%username%]: "

SET /P bunos="Enter multiple constraint values for IN clause [%constraints%]: "
ECHO you typed %constraints%
PAUSE
REM pause
"C:\Program Files\PostgreSQL\9.0\bin\psql.exe" -h %server% -U %username% -d %database% -p %port% -e -v v1=%constraints% -f test.sql

现在,在您的SQL代码文件中,在WHERE子句中或SQL中的任何其他位置添加v1标记。请注意,标记也可以在打开的SQL语句中使用,而不仅仅在文件中使用。将其保存为test.sql:

SELECT * FROM myTable
WHERE NOT someColumn IN (:v1);

在Windows中,将整个文件保存为DOS BATch文件(.bat),将test.sql保存在同一目录中,然后启动批处理文件。

感谢EnterpriseDB的Dave Page,提供原始提示脚本。

答案 4 :(得分:2)

看来你问can't be done directly from the command line。您要么必须在plpgsql中使用用户定义的函数,要么使用脚本语言调用查询(后一种方法可以更容易避免SQL注入)。

答案 5 :(得分:0)

我想提供另一个受@malcook评论(使用bash)启发的答案。

如果您需要在使用-c标志时在查询中使用外壳变量,则此选项可能对您有用。具体来说,我想获取一个表的计数,该表的名称是一个外壳变量(使用-c时不能直接传递)。

假设您拥有shell变量

$TABLE_NAME='users'

然后您可以通过使用

获得结果
psql -q -A -t -d databasename -c <<< echo "select count(*) from $TABLE_NAME;"

-q -A -t仅用于打印结果数字而无需其他格式)

我会注意到here字符串(echo运算符)中的<<<可能不是必需的,我本来以为引号本身就可以了,也许有人可以阐明原因这个。

答案 6 :(得分:0)

我最终使用了更好的@ vol7ron答案:

DO $$
BEGIN
    IF NOT EXISTS(SELECT 1 FROM pg_prepared_statements WHERE name = 'foo') THEN
        PREPARE foo(text,text,text) AS
            SELECT  * 
            FROM    foobar
            WHERE   foo = $1
                AND bar = $2
                OR  baz = $3;
    END IF;
END$$;
EXECUTE foo('foo','bar','baz');

这样,您始终可以按此顺序执行它(只有在尚未准备好查询时才准备查询),重复执行并从上一个查询中获取结果。