PostgreSQL调用另一个函数

问题描述 投票:0回答:1

我具有带有以下签名的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.

谢谢

postgresql
1个回答
0
投票

您的语句“选择项目代码,千位代码...”对所选值不执行任何操作。因此,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函数返回的数据。

© www.soinside.com 2019 - 2024. All rights reserved.