将数组变量作为参数传递给另一个函数

时间:2015-07-09 15:00:20

标签: arrays postgresql parameter-passing plpgsql stored-functions

我在一个函数中初始化了两个数组,一个用于数字(数量列表),另一个用于文本(发票列表)。我想从这个函数调用另一个函数并将这两个数组作为参数传递 我可以这样调用函数,一切正常:

select function_2('{110011-0115-7}'::text[], '{100}'::numeric[])

但是当我想发送一个包含文本数组的变量时,数组似乎是空的:

select function_2(ARRAY[invoice_list], ARRAY[amount_list]);

功能定义:

CREATE OR REPLACE FUNCTION function_1(OUT out_code1 integer
                                    , OUT out_message1 text)
  RETURNS RECORD AS
$BODY$
DECLARE
   counter      numeric;
   inv_cur      record;
   invoice_list text[];
   amount_list  numeric[]; 
BEGIN
   FOR inv_cur IN
      SELECT "ID", "AMOUNT"
      FROM "INVOICE"
      WHERE "ACCOUNT_ID" = in_account
   LOOP
       --Adding invoices to invoice array
        invoice_list[counter] := inv_cur."ID";

        --Adding amounts to amount array
        amount_list[counter] := inv_cur."AMOUNT";

        --Increasing counter for array indexes
        counter := counter + 1;
   END LOOP;

   --Caling other function
   SELECT * FROM function_2(ARRAY[invoice_list], ARRAY[amount_list]);
END
$BODY$
  LANGUAGE plpgsql VOLATILE

其他功能定义:

 CREATE OR REPLACE FUNCTION function_2(in_invoices text[]
                                     , in_amounts numeric[]) ...

1 个答案:

答案 0 :(得分:1)

您可以像这样修复您的功能:

CREATE OR REPLACE FUNCTION function_1(in_account int
                                , OUT out_code1 int
                                , OUT out_message1 text)
  RETURNS RECORD AS
$func$
DECLARE
   counter    int := 1;  -- use int and initialize
   inv_cur      record;
   invoice_list text[];
   amount_list  numeric[]; 
BEGIN

   FOR inv_cur IN
      SELECT "ID", "AMOUNT"
      FROM   "INVOICE"
      WHERE  "ACCOUNT_ID" = in_account  -- !!!
      ORDER  BY "ID" -- don't you care about sort order?
   LOOP
       --Adding invoices to invoice array
        invoice_list[counter] := inv_cur."ID";

        --Adding amounts to amount array
        amount_list[counter] := inv_cur."AMOUNT";

        --Increasing counter for array indexes
        counter := counter + 1;
   END LOOP;

   --  Calling other function
   SELECT f.outfield_1, f.outfield_2  -- replace with actual names!
   INTO  out_code1, out_message1
   FROM  function_2(invoice_list, amount_list) f;

END
$func$  LANGUAGE plpgsql VOLATILE

注释

  • 必须初始化函数变量计数器或将其设置为NULL。

  • in_account被解释为表格"INVOICE"的列名称(它可能不是)。似乎缺少一个功能参数。

  • 将我添加的ORDER BY "ID"替换为您实际需要的排序顺序。

  • 需要分配最终SELECT的结果。

  • invoice_listamount_list已经是数组。如果你想添加另一个数组维度,我们只将它们包装到另一个ARRAY图层中(我对此表示怀疑。)

现在该功能应该工作。它仍然昂贵的废话 ...

处理你的方式的数组是非常昂贵的。循环也很昂贵。将function_1()替换为此查询:

SELECT f.*
FROM  (
   SELECT function_2(array_agg("ID"), array_agg("AMOUNT")) AS f
   FROM  (
      SELECT "ID", "AMOUNT"
      FROM   "INVOICE"
      WHERE  "ACCOUNT_ID" = in_account  -- your input here!
      ORDER  BY "ID"
      ) t1
   ) t2;

您可以使用单个查询级别:

SELECT (function_2(array_agg("ID" ORDER BY "ID")
                 , array_agg("AMOUNT" ORDER BY "ID"))).*
FROM   "INVOICE"
WHERE  "ACCOUNT_ID" = in_account;

但表现会更差。带有子查询的版本只需要排序一次,并且只调用一次函数:

如果需要,可以将其包装到SQL函数中。