2

我在 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;

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

4

3 回答 3

1

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

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

select vin_temp_func('product1')

将工作。但正如你所见

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

会给你那个错误。

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

于 2014-02-07T21:39:13.213 回答
0

我也有类似的情况。

*从 prod_week_A 中选择 product_name, vin_temp_func(product_name);*

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

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

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

请尝试一下,让我知道这是否也适合您。

于 2014-03-27T13:46:33.063 回答
0

我遇到了类似的问题。

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 期间将其推回段。它比我们最初想要的要不理想,即直接将函数的输出推送到段上的表中,但是性能下降和增加主机的负载在我们看来并不是什么大问题案子。

希望您可以使这个想法适应您的问题。

祝你好运!

于 2019-10-03T18:55:06.807 回答