【问题标题】:Pass array variable as parameter to another function将数组变量作为参数传递给另一个函数
【发布时间】:2015-09-28 01:15:15
【问题描述】:

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

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

【问题讨论】:

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


    【解决方案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

    注意事项

    • 函数变量counter必须初始化或者设置为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 函数中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-07
      • 1970-01-01
      • 2013-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多