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


92

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

例:

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

寻找类似的东西:

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

请提供更多背景信息。该查询是在SQL文件中,在Perl / Python / Ruby / <在此处插入喜欢的脚本语言>脚本中还是在其他地方?

@杰克:我想直接从psql提示符(命令行)执行此操作。我正在从脚本中获取代码,但不想进行整个查找/替换过程。
vol7ron 2011年

@ Vol7ron,请参阅下面的答案以获取psql命令行示例。
MAbraham12年

1
@ MAbraham1:很好。我应该为我的问题提供更多背景知识。我有很多在开放文本中都有SQL的脚本。有时,使用自定义值进行调试可以很方便地将它们带到数据库中,然后直接将它们击中。我一直在寻找一种在Postgres内轻松完成此操作的方法,而无需保存其他文件。
vol7ron 2012年

@ Vol7ron,谢谢。我在考虑批处理作业,但是您也应该能够在开放SQL中使用令牌。如果您喜欢我的回答,请不要忘记投票。
MAbraham1年

Answers:


178

您可以使用-v构造,例如

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

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

select * from table_1 where id = :v1;

请注意我们如何使用两个引号传递字符串/日期值 " '...' "


2
+1有趣,传递命名参数。登录后,您知道执行此操作的任何方式吗?
vol7ron 2011年

9
当然,只需使用即可\set v3 'another value'。只需记住,当您需要在SQL语句中引用值时,请在变量名称周围使用撇号,如下所示:SELECT * FROM foo WHERE bar = :'v3';
Cromax

1
我想他们是从awk
Neil McGuigan

1
可以@来代替:像SQLSERVER
AWAIS马哈茂德

4
注意,阅读本文后,我希望发现用-v设置的变量可用于用-c执行的命令,但是,可惜它们没有。换句话说, psql -v v1=12 -v v2="'Hello World'" -v v3="'2010-11-12'" -c 'select * from table_1 where id = :v1;' 会产生语法错误。但是,如果bash是您的外壳,则可以尝试: psql -v v1=12 -v v2="'Hello World'" -v v3="'2010-11-12'" <<< 'select * from table_1 where id = :v1;' 取得良好效果。
malcook

30

在PostgreSQL中可以找到PREPARE语句,就像使用脚本语言一样。不幸的是,您仍然不能使用?,但是您可以使用$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;

@IvanBlack还有其他要包含的内容吗?:)释放是在会话结束时自动执行的
-vol7ron

只需注意,现在foo繁忙,另一个PREPARE在当前会话未关闭时应该使用其他名称。如果你玩PREPAREpsql很难每次去创造一个新的名称,DEALLOCATE可以用它帮助=)
伊万黑色

感谢您提及这一点。我已经有一段时间没有使用PREPARE了,但这是有用的信息
vol7ron

这个解决方案是IMO很好的。一个有用的副作用-您可以轻松地多次调用已准备好的语句。
尤里(Yuri)

13

在psql中,通过

\set name val

命令,应该与-v name=val命令行选项相关联。报价很痛苦,在大多数情况下,将整个查询内容放入shell这里文档更容易。

编辑

糟糕,我应该说是以前的答复,-v而不是-P(用于格式化选项)。


7

您也可以在psql命令行或批处理文件中传递参数。前几条语句收集了连接到数据库所需的详细信息。

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

@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提供原始的提示脚本。


Windows示例为+1;尽管大多数Pg数据库都以* nix变体形式存在
vol7ron 2012年

2

看来您要求的内容不能直接从命令行完成。您要么必须在plpgsql中使用用户定义的函数,要么从脚本语言调用查询(后一种方法使避免SQL注入变得容易一些)。


不是我吗?很多时候,我希望即使是匿名离开,投票表决也需要某种解释(类似于我们投票决定关闭问题的原因)。
vol7ron 2012年
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.