我在使用?
占位符的脚本中有一个详细的查询。我想直接从psql命令行(脚本外部)测试这个相同的查询。我想避免进入并用实际值替换所有?
,而是在查询之后传递参数。
示例:
SELECT *
FROM foobar
WHERE foo = ?
AND bar = ?
OR baz = ? ;
寻找类似的东西:
%> {select * from foobar where foo=? and bar=? or baz=? , 'foo','bar','baz' };
答案 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');
这样,您始终可以按此顺序执行它(只有在尚未准备好查询时才准备查询),重复执行并从上一个查询中获取结果。