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

Pass array variable as parameter to another function

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

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[]) ...

您可以像这样修复函数:

CREATE OR REPLACE FUNCTION function_1(<b>in_account int</b>
                                , OUT out_code1 int
                                , OUT out_message1 text)
  RETURNS RECORD AS
$func$
DECLARE
   <b>counter    int := 1;</b>  -- 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  -- !!!
      <b>ORDER  BY "ID"</b> -- 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 <b>f.outfield_1, f.outfield_2</b>  -- replace with actual names!
   <b>INTO  out_code1, out_message1
   FROM  function_2(invoice_list, amount_list) f</b>;

END
$func$  LANGUAGE plpgsql VOLATILE

备注

  • 函数变量counter必须初始化或设置为NULL。

  • in_account 被解释为 table "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;

但是性能会差很多。带有子查询的版本只需要排序一次并且也只调用函数一次:

  • How to avoid multiple function evals with the (func()).* syntax in an SQL query?

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