在PostgreSQL中将元素分配给具有属性的数组索引。

huangapple go评论56阅读模式
英文:

Assign Element To Index of Array with Attribute in PostgreSSQL

问题

I have an oracle code like this:

FOR loop1 IN cursor1 LOOP
array1.EXTEND;
array1(loop1).cur_name := cursor1.name;
array1(loop1).cur_value := cursor1.value;
END LOOP;

我有一个类似这样的Oracle代码:

FOR loop1 IN cursor1 LOOP
array1.EXTEND;
array1(loop1).cur_name := cursor1.name;
array1(loop1).cur_value := cursor1.value;
END LOOP;

I tried to convert to PostgreSQL like this, but it's getting an error:

DECLARE 
  cursor1 cursor for select name, value from table;
  array1   text[];
BEGIN
  -- Do something
  ...

  FOR loop1 IN cursor1 LOOP
    array1[loop].cur_name := cursor1.name; --error here
    array1[loop1].cur_value := cursor1.value; -- error here
  END LOOP;

  -- Do something
  ...
  RETURN;
END;

我尝试将它转换成 PostgreSQL,但出现了错误:

DECLARE 
  cursor1 cursor for select name, value from table;
  array1   text[];
BEGIN
  -- Do something
  ...

  FOR loop1 IN cursor1 LOOP
    array1[loop].cur_name := cursor1.name; -- 在这里出错
    array1[loop1].cur_value := cursor1.value; -- 在这里出错
  END LOOP;

  -- Do something
  ...
  RETURN;
END;

Is there any method to create an array with an attribute name?
有没有办法创建具有属性名的数组?

英文:

Can I assign a value from cursor to index of array with attribute?

I have an oracle code like this :

cursor cursor1 is select name, value from table;

FOR loop1 IN cursor1 LOOP
array1.EXTEND;
array1(loop1).cur_name := cursor1.name;
array1(loop1).cur_value := cursor1.value;
END LOOP;

i tried to convert to postgresql like this, but it's getting error

CREATE FUNCTION function_name () RETURNS something AS $$
DECLARE 
  cursor1 cursor for select name, value from table;
  array1   text[];
BEGIN
  -- Do something
  ...

  FOR loop1 IN cursor1 LOOP
    array1[loop].cur_name := cursor1.name; --error here
    array1[loop1].cur_value := cursor1.value; -- error here
  END LOOP;

  -- Do something
  ...
  RETURN;
END;

is there any method to create an array with attibute name?

答案1

得分: 2

Oracle函数返回一个集合(如果我没记错的话,是一个“关联数组”),但已经有一段时间了。Postgres没有集合,最接近的数据类型是数组。然而,由于您的集合包含多列,您需要创建一个用户定义类型(UDT),然后您的函数返回该类型的数组。(注意:我假设了表中的数据类型。请根据需要更正。)

create type name_val as (name text, value integer);

create or replace function function_name () 
    returns name_val[]
    language plpgsql
as $$
declare 
  cursor1 cursor for
          select name, value
            from test
           limit 10;  

  rec     record;
  array1  name_val[];  
  l_name_val name_val; 
begin
  -- 做一些操作

  for rec in cursor1
  loop
    l_name_val.name = rec.name;
    l_name_val.value = rec.value; 
    array1 = array1 || l_name_val;
  end loop

  -- 做一些操作

  return array1;
end;
$$;

还有其他几种选项可以完全避免使用游标和循环。假设您确实需要返回一个数组,您可以将上述函数简化为一个单独的SQL语句:

create or replace function function_name3()
   returns name_val[]
  language sql
as $$
    select array_agg((name, value)::name_val) 
      from test 
     limit 10;
$$;

演示在这里


更新:<br/>
我注意到,在我回答后,您将问题从 for loop1 in 1 .. 10 ... 更改为 for rec in cursor1 ...,从而删除了结果行的限制。您只需删除Limit 10子句即可达到相同的效果。

英文:

The Oracle function is returning a collection (An Associative Array if I remember correctly, but its been awhile). Postgres does NOT have collections, the closest data type is an array. However since your collection contains multiple columns, you need to create a UDT (user defined type}, then your function returns an array of that type. (Note I assumed the data types in the table. Correct as deeded.)

create type name_val as (name text, value integer); 

create or replace function function_name () 
    returns name_val[]
   language plpgsql
as $$
declare 
  cursor1 cursor for
          select name, value
            from test
           limit 10;  
        
  rec     record;
  array1  name_val[];  
  l_name_val name_val; 
begin
  -- do something
 

  for rec in cursor1
  loop
    l_name_val.name = rec.name;
    l_name_val.value = rec.value; 
    array1 = array1 || l_name_val;
  end loop;

  -- do something
  
  return  array1;
end;
$$;

There are a couple other option which avoid the cursor and looping altogether. Assuming you actually need any Array returned you can reduce the above function to a single sql statement:

create or replace function function_name3()
   returns name_val[]
  language sql
as $$
    select array_agg((name, value)::name_val) 
      from test 
     limit 10;
$$;

Demo Here


UPDATE: <br/>
I noticed that subsequent to my answer you update the question from for loop1 in 1 .. 10 ... to for rec in cursor1 ... thus removing the resulting row limitation. You accomplish the same by just removing the Limit 10 clause.

huangapple
  • 本文由 发表于 2023年2月6日 07:10:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75356135.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定