我具有带有以下签名的PostgreSQL函数。
CREATE OR REPLACE FUNCTION GetResults (Weight numeric, documents boolean, country_code text)
RETURNS TABLE (
itemcode varchar(20)
,kilocode varchar(20)
) AS $$
DECLARE
.....
END; $$
LANGUAGE 'plpgsql'
现在,我需要创建另一个函数,并使用上述函数的结果(商品代码,千码)。这就是我尝试使用上述功能的方式
CREATE OR REPLACE FUNCTION GetProductList(
country_code text,
maxdim numeric,
weight numeric,
volume numeric,
promo_code character varying,
documents boolean)
RETURNS TABLE(code varchar (20)
, cms_code varchar (20)
, service_code varchar (20)
, service_name varchar (10)
, service_group varchar (1000)
, signature_required boolean
, service_promo_code varchar (10))
LANGUAGE 'plpgsql'
AS $$
DECLARE
var_pg_rec record;
sqlToExecute varchar(1000);
val_true boolean := 't';
BEGIN
.....
FOR var_pg_rec IN EXECUTE sqlToExecute USING Weight, country_code, val_true
LOOP
Select itemcode , kilocode from GetResults (Weight, documents, country_code);
code := var_pg_rec.ProductGroupName || itemcode;
cms_code := var_pg_rec.ProductGroupName || kilocode;
service_code := 'DummyService';
service_name := 'Dummy Service 10.0kg';
service_group := 'Dummy Service 10.0kg';
signature_required := false;
service_promo_code := 'dummyPro';
RETURN NEXT;
END LOOP;
END $$;
执行上述操作时,出现以下错误
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
谢谢
您的语句“选择项目代码,千位代码...”对所选值不执行任何操作。因此,Postgres当时不知道您打算以后使用它们。为了告诉Postgres这个事实,您需要提供一个location来保存结果。您可以通过遍历GetResults函数的结果集(返回表的函数可以返回多行)或在函数中更改为“ Select ... into ...”格式来实现此目的。以下是每个示例的演示。由于您没有发布完整的例程,因此我使用了一些本地例程,因此我必须生成随机数据元素。这些例程都以SOQ开始。我进一步评论了我在哪里更改了您的例程;
数据生成例程:
create or replace function soq.random_int(
l integer,
h integer)
returns integer
language sql strict
as $$
select floor(random() * (h-l+1) + l)::integer;
$$;
create or replace function soq.random_keyboard_char()
returns text
language sql
as $$
with keyboard_char as
( select array[ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_', '$', '#'
, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] ca
)
select ca[soq.random_int(1,array_length(ca,1))]::text from keyboard_char;
$$;
create or replace function soq.random_text(max_length_in integer)
returns text
language sql strict
as $$
with recursive t(n,cl) as
( select 1, soq.random_keyboard_char()
union all
select t.n+1, concat(t.cl,soq.random_keyboard_char())
from t
where n<=max_length_in
)
select cl from t where n = max_length_in;
$$;
有了这个,现在您的例程。首先假设GetResuts返回多行。
CREATE OR REPLACE FUNCTION GetResults (Weight numeric, documents boolean, country_code text)
RETURNS TABLE (
itemcode varchar(20)
,kilocode varchar(20)
)
AS $$
declare
lcnt integer :=1;
begin
if documents
then
lcnt = weight::integer;
end if;
while lcnt > 0
loop
select soq.random_text(20),soq.random_text(20) into itemcode,kilocode;
return next;
end loop;
return;
END; $$
LANGUAGE 'plpgsql' ;
CREATE OR REPLACE FUNCTION GetProductList(
country_code text,
maxdim numeric,
weight numeric,
volume numeric,
promo_code character varying,
documents boolean)
RETURNS TABLE(code varchar (20)
, cms_code varchar (20)
, service_code varchar (20)
, service_name varchar (10)
, service_group varchar (1000)
, signature_required boolean
, service_promo_code varchar (10))
LANGUAGE 'plpgsql'
AS $$
DECLARE
var_pg_rec record;
sqlToExecute varchar(1000);
val_true boolean := 't';
results record; -- added
BEGIN
sqlToExecute = $stmt$ -- added
with gl as (select * from generate_series (1, coalesce($1::integer,1) )) -- added
Select 'Group_' || row_number() over() || '::' as ProductGroupName -- added
, $2 -- added
, $3 -- added
from gl ; -- added
$stmt$; -- added
--..... -- commented
FOR var_pg_rec IN EXECUTE sqlToExecute USING Weight, country_code, val_true
LOOP
for results in ( select * from GetResults (Weight, documents, country_code) ) -- changed
loop -- added
code := var_pg_rec.ProductGroupName || results.itemcode; -- changed
cms_code := var_pg_rec.ProductGroupName || results.kilocode; -- changed
service_name := 'Dummy Service 10.0kg';
service_group := 'Dummy Service 10.0kg';
signature_required := false;
service_promo_code := 'dummyPro';
RETURN NEXT;
end loop; -- added
END LOOP;
return ; -- added
end;
$$ ;
最后,如果您知道GetProducts函数始终返回丢失的1行,则为GetProductList函数的替代方法。
CREATE OR REPLACE FUNCTION GetProductList(
country_code text,
maxdim numeric,
weight numeric,
volume numeric,
promo_code character varying,
documents boolean)
RETURNS TABLE(code varchar (20)
, cms_code varchar (20)
, service_code varchar (20)
, service_name varchar (10)
, service_group varchar (1000)
, signature_required boolean
, service_promo_code varchar (10))
LANGUAGE 'plpgsql'
AS $$
DECLARE
var_pg_rec record;
sqlToExecute varchar(1000);
val_true boolean := 't';
results record;
l_itemcode text;
l_kilocode text; -- added
BEGIN
sqlToExecute = $stmt$ -- added
with gl as (select * from generate_series (1, coalesce($1::integer,1) )) -- added
Select 'Group_' || row_number() over() || '::' as ProductGroupName -- added
, $2 -- added
, $3 -- added
from gl ; -- added
$stmt$; -- added
--..... -- commented
FOR var_pg_rec IN EXECUTE sqlToExecute USING Weight, country_code, val_true
LOOP
select itemcode,kilocode -- changed
into l_itemcode, l_kilocode -- changed
from GetResults (Weight, documents, country_code); -- changed
code := var_pg_rec.ProductGroupName || l_itemcode; -- changed
cms_code := var_pg_rec.ProductGroupName || l_kilocode; -- changed
service_name := 'Dummy Service 10.0kg';
service_group := 'Dummy Service 10.0kg';
signature_required := false;
service_promo_code := 'dummyPro';
RETURN NEXT; -- added
END LOOP;
return ; -- added
end;
$$ ;
注意每个版本如何处理从GetResults函数返回的数据。