postgres中的动态sql查询

Posted

技术标签:

【中文标题】postgres中的动态sql查询【英文标题】:dynamic sql query in postgres 【发布时间】:2012-09-28 14:50:10 【问题描述】:

我试图使用动态 SQL 在 postgres 中运行一些查询。

例子:

EXECUTE format('SELECT * from result_%s_table', quote_ident((select id from ids where condition = some_condition)))

我必须查询一个格式为 result_%s_table 的表,其中我需要从另一个表中替换正确的表名(一个 id)。

我收到错误ERROR: prepared statement "format" does not exist

链接:string substitution with query result postgresql

【问题讨论】:

【参考方案1】:

这些看起来都比 OP 的问题复杂。不同的格式应该可以解决问题..但绝对可能是我不明白的情况。

从我阅读 OP 问题的方式来看,我认为处于类似情况的其他人可能会从我的方法中受益。

我在 Redshift 上使用 Postgre,我遇到了这个问题并找到了解决方案。

我试图创建一个动态查询,输入我自己的日期。

date = dt.date(2018, 10, 30)

query = ''' select * from table where date >= ''' + str(my_date) + ''' order by date '''

但是,以这种方式输入时,查询完全忽略了条件。

但是,如果使用百分号 (%),则可以正确插入日期。

上述语句的一种正确写法是:

query = ''' select * from table where date >= ''' + ''' '%s' ''' % my_date + ''' order by date '''

所以,也许这有帮助,也可能没有。我希望它至少对我的情况有帮助!

最好的祝愿。

【讨论】:

【参考方案2】:
CREATE OR REPLACE FUNCTION public.exec(
text)
RETURNS SETOF RECORD
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN 
    RETURN QUERY EXECUTE $1 ; 
END 
$BODY$;

用法:

select * from exec('select now()') as t(dt timestamptz)

【讨论】:

这很简单,非常适合日常使用...展示如何将动态查询用作普通查询! 太棒了!安全只读运行动态 SQL。 . select * from run_select('update a set i = 5;') as t(account_id int);错误:无法将 UPDATE 查询作为游标打开;【参考方案3】:

尝试使用

RETURN QUERY EXECUTE '<SQL Command>'

这会将数据返回为表格形式。您必须将其用于 PostgreSQL 的存储功能。

我已经创建了关于使用 PostgreSQL 的动态查询的自定义过滤器和自定义排序的完整演示。 请访问此网址: http://www.dbrnd.com/2015/05/postgresql-dynamic-sql/

【讨论】:

【参考方案4】:

EXECUTE ... USING 仅适用于PL/PgSQL - 即在函数中或用PL/PgSQL 语言编写的DO blocks 中。它不适用于纯 SQL;普通 SQL 中的 EXECUTE 完全不同,用于执行准备好的语句。不能在 PostgreSQL 的 SQL 方言中直接使用动态 SQL。

比较:

PL/PgSQL's EXECUTE ... USING;到 SQL's EXECUTE

查看my prior answer中的倒数第二个标准杆。


除了在 PL/PgSQL 中不运行之外,您的 SQL 语句是错误的,它不会按照您的预期运行。如果(select id from ids where condition = some_condition) 返回42,如果id 是整数,则语句将失败。如果将其转换为文本,您会得到:

EXECUTE format('SELECT * from result_%s_table', quote_ident('42'));
EXECUTE format('SELECT * from result_%s_table', '"42"');
EXECUTE 'SELECT * from result_"42"_table';

这是无效的。你实际上想要result_42_table"result_42_table"。你必须写一些更像:

EXECUTE format('SELECT * from %s', quote_ident('result_'||(select id from ids where condition = some_condition)||'_table'))

...如果您必须使用quote_ident

【讨论】:

作为补充,DO 块总是返回 void 并且不接受任何参数,所以我认为 OP 仅限于一个函数。 @Clodoaldo 好点子——他们可以执行SELECT,但除非他们做一些真正迂回的事情,比如SELECT ... INTO一个临时表。 @CraigRinger 你好,我知道我参加聚会有点晚了,但你能推荐任何关于 postgreSQL 中动态 sql 的好教程吗?我找不到任何东西。我想创建一个多合一的动态查询。如果需要,请检查 this 问题。谢谢 "您不能在 PostgreSQL 的 SQL 方言中直接使用动态 SQL。"好吧,事实上你可以,至少使用 query_to_xml。见***.com/a/38684225/3935325 postgres 是否有任何扩展以编程方式生成动态 sql 给定参数?【参考方案5】:

EXECUTE 仅适用于 pl/pqsql 环境。

用 SELECT 代替 EXECUTE 尝试

 SELECT format('SELECT * from result_%s_table', quote_ident((select id from ids where condition = some_condition))

输出将是动态查询。

【讨论】:

动态查询的文本,当然,但它不会执行查询。请参阅之前的链接帖子。 是的,我已经完成了你详细的动态 qry 执行,这里我提到的是 EXECUTE 只能在 pl/pqsql 环境中工作,当我发布我的答案时,我真的没有注意到你的回应. 不用担心。它只是没有回答问题,即如何执行动态SQL。 那么上面的语句应该在 pl/pqsql 块中,我在第一行本身就提到了。 我考虑过投反对票,因为如前所述,这不会执行该块。但是,获取查询结果并将其作为另一个查询调用再次提供并不难,动态内容是可信的。所以这解决了问题,理论上避免了注入。

以上是关于postgres中的动态sql查询的主要内容,如果未能解决你的问题,请参考以下文章

sql postgres中的SQL查询

Excel 中动态 SQL 查询的性能问题

sql Postgres查询列表和kill查询

Postgres 的 SQL 查询

将 T-SQL 查询转换为 Postgres

如何在没有连接的情况下为 postgres (Redshift) 生成 SQL 查询?