【问题标题】:function cannot execute on segment because it accesses relation函数无法在段上执行,因为它访问关系
【发布时间】:2014-02-06 22:13:15
【问题描述】:

我在 Greenplum postgres 中有如下定义的函数

CREATE OR REPLACE FUNCTION vin_temp_func(j text) RETURNS integer AS $$
Declare varx integer;
BEGIN
select count(*) into varx
from T_perf a
left join T_profile b on a.sr_number = b.sr_number  where b.product_name like '%V1%' and
a.submit_date >= (('2013-02-01'::date - CAST(EXTRACT(DOW FROM '2013-02-01'::date) as int)) - 7)+'1 week'::interval and 
a.submit_date <= ('2013-02-01'::date - CAST(EXTRACT(DOW FROM '2013-02-01'::date)+1 as int)) + '1 week'::interval+'23 hours'::interval+'59 minutes'::interval+'59 seconds'::interval
and b.product_name = j;
RETURN varx;
        END;
$$ LANGUAGE plpgsql;

表是这样定义的

drop table if exists prod_week_A;

create table prod_week_A as (
select product_name 
from T_profile where product_name like '%V1%' limit 100)

当我尝试执行以下操作时,我收到错误“函数无法在段上执行,因为它访问关系”

select product_name, vin_temp_func(product_name) 
from prod_week_A limit 100;

有人可以帮我解决这个问题吗?谢谢!

【问题讨论】:

    标签: sql greenplum


    【解决方案1】:

    与 Postgress 相比,Greenplum 中的功能有限。如果一个函数访问一个“关系”(想想表),你不能在另一个表的选择中调用它。

    所以可以手动调用你的函数

    select vin_temp_func('product1')

    会起作用。但是如你所见

    select product_name, vin_temp_func(product_name) from prod_week_A limit 100;

    会给你这个错误。

    您也许可以将函数重写为视图,这在很多情况下都是可能的,但在这里可能会很困难。

    【讨论】:

      【解决方案2】:

      我也遇到过类似情况。

      *select product_name, vin_temp_func(product_name) from prod_week_A;*

      有效的方法很奇怪,我对此并不了解。我限制了我从中提取行的表的结果。 所以

      *select product_name, vin_temp_func(product_name) from (select product_name from prod_week_A limit 10000000) a;*

      我在 limit 前面放了一个巨大的数字来返回所有的行。这需要时间(不应该),但这很有效。

      请尝试一下,如果这也适合您,请告诉我。

      【讨论】:

        【解决方案3】:

        我遇到了类似的问题。

        INSERT INTO tableX SELECT * from function_name(...);
        

        Wes Reing 的观点似乎是准确的 AFAIK——GPDB 真的不想从引用另一个表的语句中调用您的函数。所以我决定拆开pl/sql中的部分。

        DO $$
        DECLARE 
          myrow myrowtype;
        BEGIN
          SELECT * FROM function_name(...) INTO myrow;
          INSERT INTO tableX (...) (SELECT myrow.*);
          RETURN;
        END;
        $$ LANGUAGE plpgsql;
        

        这会在 master(?) 上收集函数的输出,然后在 INSERT 期间将其推送回段。它比我们最初想要的要不理想,即直接将函数的输出推到段上的表中,但是性能下降和增加的负载在我们的案例。

        希望你能根据你的问题调整这个想法。

        祝你好运!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-12-22
          • 2021-08-10
          • 1970-01-01
          • 1970-01-01
          • 2015-11-20
          • 2017-12-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多