将数组变量作为参数传递给另一个函数
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_list
和 amount_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 函数中。
我在一个函数中初始化了两个数组,一个用于数字(金额列表),另一个用于文本(发票列表)。我想从这个函数调用另一个函数并将这两个数组作为参数传递。
我可以这样调用函数,一切正常:
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_list
和amount_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 函数中。