如何在 postgres 的函数中传递和数组并修改它
How to pass and array and modify it in a function in postgres
我正在尝试编写一个函数来执行此操作:基本上创建一个数组,其数据元素与传递给函数的数组相同,但有时会有一些变化——比如如果某个元素是偶数,那么标志应该改变从 N 到 Y。该过程将具有两个元素的数组作为输入 - 一个数字和一个标志。例如。 (1,'N'), (2,'N')。现在,如果传递的数字是偶数,那么 proc 应该修改该值并更改为 (2,'Y') 而另一个保持为 (1,'N')。
基本上我的数组基础知识不清楚,阅读细节也没有帮助所以这个问题。
我尝试了以下方法,但它不起作用...你能建议一下吗:
CREATE TYPE test_n_t_num AS (
v_n double precision,
is_even character varying(1));
create function temp_n_proc_2(p_nums IN OUT test_n_t_num[])
as
$$
declare
v_nums test_n_t_num[];
v_cnt double precision;
BEGIN
v_cnt := cardinality(p_nums);
v_nums := ARRAY[]::test_n_t_num[];
for i in 1..v_cnt LOOP
if p_nums[i].v_n_double % 2 = 0 then
v_nums [i].is_even := 'Y';
p_nums [i].is_even := 'Y'
else
v_nums [i].is_even := p_nums [i].is_even;
end if;
v_nums[i] := {p_nums[i].v_n,v_nums [i].is_even};
END LOOP;
END;
$$
language plpgsql;
稍后我还需要遍历并打印出数组 v_nums 中的值 - 一个在函数中定义的值。
谢谢,
尼拉夫
我以前在尝试做这类事情时遇到过类似的问题。基本上你不能使用数组符号分配给复合对象,即 your_array[1].field := value
不起作用。这是一些有用的东西(我不使用 cardinality
因为我还在 9.3 上并且是在 9.4 中添加的):
CREATE TYPE public.test1 AS (a INTEGER, is_even BOOLEAN);
CREATE OR REPLACE FUNCTION f1(ar INOUT public.test1[]) AS $$
DECLARE
t public.test1;
BEGIN
RAISE NOTICE '%', ar;
FOR i IN 1..ARRAY_LENGTH(ar, 1) LOOP
t := ar[i];
t.is_even := t.a % 2 = 0;
ar[i] := t;
END LOOP;
RAISE NOTICE '%', ar;
END
$$ LANGUAGE plpgsql;
所以基本上创建一个该类型的变量,将索引项读入变量,修改字段,然后将变量的内容复制回数组。
SELECT * FROM f1('{"(1,)","(4,)","(6,)"}'::public.test1[])
returns {"(1,f)","(4,t)","(6,t)"}
打印的消息(这是使用 pgadmin 3)是:
NOTICE: {"(1,)","(4,)","(6,)"}
NOTICE: {"(1,f)","(4,t)","(6,t)"}
我正在尝试编写一个函数来执行此操作:基本上创建一个数组,其数据元素与传递给函数的数组相同,但有时会有一些变化——比如如果某个元素是偶数,那么标志应该改变从 N 到 Y。该过程将具有两个元素的数组作为输入 - 一个数字和一个标志。例如。 (1,'N'), (2,'N')。现在,如果传递的数字是偶数,那么 proc 应该修改该值并更改为 (2,'Y') 而另一个保持为 (1,'N')。
基本上我的数组基础知识不清楚,阅读细节也没有帮助所以这个问题。
我尝试了以下方法,但它不起作用...你能建议一下吗:
CREATE TYPE test_n_t_num AS (
v_n double precision,
is_even character varying(1));
create function temp_n_proc_2(p_nums IN OUT test_n_t_num[])
as
$$
declare
v_nums test_n_t_num[];
v_cnt double precision;
BEGIN
v_cnt := cardinality(p_nums);
v_nums := ARRAY[]::test_n_t_num[];
for i in 1..v_cnt LOOP
if p_nums[i].v_n_double % 2 = 0 then
v_nums [i].is_even := 'Y';
p_nums [i].is_even := 'Y'
else
v_nums [i].is_even := p_nums [i].is_even;
end if;
v_nums[i] := {p_nums[i].v_n,v_nums [i].is_even};
END LOOP;
END;
$$
language plpgsql;
稍后我还需要遍历并打印出数组 v_nums 中的值 - 一个在函数中定义的值。
谢谢, 尼拉夫
我以前在尝试做这类事情时遇到过类似的问题。基本上你不能使用数组符号分配给复合对象,即 your_array[1].field := value
不起作用。这是一些有用的东西(我不使用 cardinality
因为我还在 9.3 上并且是在 9.4 中添加的):
CREATE TYPE public.test1 AS (a INTEGER, is_even BOOLEAN);
CREATE OR REPLACE FUNCTION f1(ar INOUT public.test1[]) AS $$
DECLARE
t public.test1;
BEGIN
RAISE NOTICE '%', ar;
FOR i IN 1..ARRAY_LENGTH(ar, 1) LOOP
t := ar[i];
t.is_even := t.a % 2 = 0;
ar[i] := t;
END LOOP;
RAISE NOTICE '%', ar;
END
$$ LANGUAGE plpgsql;
所以基本上创建一个该类型的变量,将索引项读入变量,修改字段,然后将变量的内容复制回数组。
SELECT * FROM f1('{"(1,)","(4,)","(6,)"}'::public.test1[])
returns {"(1,f)","(4,t)","(6,t)"}
打印的消息(这是使用 pgadmin 3)是:
NOTICE: {"(1,)","(4,)","(6,)"}
NOTICE: {"(1,f)","(4,t)","(6,t)"}