为啥函数结果保存较晚?

Posted

技术标签:

【中文标题】为啥函数结果保存较晚?【英文标题】:why results of function save late?为什么函数结果保存较晚? 【发布时间】:2019-04-04 08:29:33 【问题描述】:

今天我遇到了一个奇怪的问题。我想在视图中调用 plpgsql 函数(我知道调用函数是一种糟糕而奇怪的方式,所以请不要在你的答案中提及它)。我这样做了,但函数的结果在显示视图结果后应用!!!

我想知道这怎么可能?以及如何在完成查询之前强制 pgpgsql 函数存储其结果?

关于我的代码的一些信息:

plan:这是一张关于旅行计划的表格,包括 date_of_travel、价格等。

travel_check():这是一个函数,它从计划表中删除那些 date_of_travel 小于 current_date 的记录,并将它们存储到另一个表并返回一个整数。(这并不重要,只要记住这个函数删除一些记录来自计划表)但我在下面写了确切的定义:

    create or replace function finish_travel(todelete integer) returns void as
        $body$
        begin
            create table if not exists history_of_travel(
                id integer,
                traveldate date,
                source_id char(3),
                destination_id char(3),
                timeofday time
            );
            insert into history_of_travel
              select id,traveldate,source_id,destination_id,timeofday
              from plan
              where id=todelete;
            delete from plan where id=todelete;
        end;
        $body$
        language plpgsql volatile;


        create or replace function travel_check() returns int as
        $body$
        declare
          trip record;
        begin
            for trip in select *
                          from plan
            loop
                if(trip.traveldate<current_date) then
                    perform finish_travel(trip.id);
                end if;
                if(trip.traveldate=current_date and trip.timeofday=now()::timestamp(0)::time) then
                    perform finish_travel(trip.id);
                end if;
            end loop;
            return 1;
        end;
        $body$
        language plpgsql volatile;

我想创建一个包含两个步骤的视图:

    调用函数和更新计划。 显示计划的记录。

我试过下面的代码

           create view clients_select_query as
                       select plan.*
                       from plan,(select travel_check()) as d
                        where exists(select * from plan)

当我跑步时:

    select * from  clients_select_query

不幸的是它显示计划表的内容没有任何变化

但如果我再次运行:

    select * from  clients_select_query

    select * from plan

我看到更改已应用。

如何在不更改方法的情况下首次运行查询后查看更改?

如果不清楚,请告诉我函数、表和视图的确切定义

【问题讨论】:

我认为我们需要你的函数代码来更好地理解你想要做什么。 @Arkhena,我编辑了我的问题。谢谢你的评论 【参考方案1】:

结果不是“保存较晚”,但 Postgres 对您隐藏更改,以便查询行为可预测。

Postgres 的concurrency control 表示查询在开始运行后不会看到任何更改。即使您自己的查询正在进行更改也是如此,并且没有办法避免它。

相反,您可以创建一个 set-returning 函数,它首先执行删除操作,然后使用第二个查询返回表的内容。然后,创建一个从该函数中进行选择的视图。

create function clients_select_function() returns setof plan as $$
  select travel_check();
  select * from plan;
$$
language sql;

create view clients_select_query as
  select * from clients_select_function();

【讨论】:

非常感谢,这是问题的确切原因和一个很好的解决方案,它工作正常。

以上是关于为啥函数结果保存较晚?的主要内容,如果未能解决你的问题,请参考以下文章

为啥此控件不将结果保存回数据库?

为啥在 WPF 中将 BitmapSource 保存为 bmp、jpeg 和 png 时会得到完全不同的结果

为啥 MySQL 给出错误“不允许从函数返回结果集”?

为啥两个函数不记录相同的结果?

excel中countif函数显示的结果为啥不对?

为啥压缩函数和可迭代的结果不起作用? [复制]