Postgresql 9.2 中在查询中调用函数的正确方法

Posted

技术标签:

【中文标题】Postgresql 9.2 中在查询中调用函数的正确方法【英文标题】:Correct way in Postgresql 9.2 to call a function in a query 【发布时间】:2014-03-13 18:08:05 【问题描述】:

我今天注意到我的日志文件有些奇怪。我看到一个“通知”被一遍又一遍地登录。而且我想我已经找到了原因,但不理解它或解决方法。

查询是:

select (get_account_details(account.id)).* from account where id in (113126123254, 116261470380);

get_account_details 将在某些情况下记录一条消息 - 一种情况是帐户具有 daily_spend_limit。在我的日志中我看到:

NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 116261470380 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00
NOTICE:  Account 113126123254 has a daily_spend_limit of 10.00.  Remaining balance as been calculated as 10.00

莫名其妙,但我终于注意到它被调用了 17 次 where account.这是帐户表中的确切列数。

如果我跑:

select * from get_account_details(113126123254);

我只记录了 1 条通知。

这里发生了什么以及我如何“正确”编写此查询?

【问题讨论】:

【参考方案1】:

我不明白为什么更简单的构造会为每一列调用一次函数,但这是抑制它的一种方法:

select (get_account_details).* from 
(
    select get_account_details(account.id) from account 
         where id in (113126123254, 116261470380)
) foo

由于您无法重现,而且我手边没有您的架构,所以让我从头开始创建架构:

create table foo (id integer, a text, b text, c text, d text, e text);
insert into foo (id) select * from generate_series(1,4);
create function get_foo(int) returns setof foo as $$ BEGIN 
    RAISE NOTICE 'dfjkl'; 
    return query select * from foo where id=$1; 
END $$ language plpgsql;

现在执行这些,第一个给出 12 NOTICE,第二个给出 2。

select (get_foo(id)).* from foo where id in (1,2);
select (get_foo).* from (select get_foo(id) from foo where id in (1,2)) ssss;

【讨论】:

我刚刚测试了您的解决方案,得到了相同的日志输出。

以上是关于Postgresql 9.2 中在查询中调用函数的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

Postgresql 9.2 错误与 group by 未出现在 postgresql 12 中

有没办法在postgreSQL中查询oracle上的数据

播放框架中未解决的 postgresql 9.2 jar 依赖关系

在 postgresql 中输出多个 sql 查询的结果

PostgreSQL——查询优化——预处理

PostgreSQL——查询优化——预处理