当列数据类型是复合类型时,如何使用PostgreSQL传输数组中的列?

时间:2016-01-21 22:55:01

标签: sql postgresql plpgsql

我正在使用PostgreSQL 9.4,我正在尝试在数组中传输列值。对于“普通”(非用户定义)数据类型,我可以使用它。

为了详细解释我的问题,我编写了一个最小的例子。 假设我们定义一个复合类型“compo”并创建一个表“test_rel”并插入一些值。看起来像这样,对我有用:

    CREATE TYPE compo AS(a int, b int);
    CREATE TABLE test_rel(t1 compo[],t2 int);
    INSERT INTO test_rel VALUES('{"(1,2)"}',3);
    INSERT INTO test_rel VALUES('{"(4,5)","(6,7)"}',3);

接下来,我们尝试获取包含列t2值的数组。以下也有效:

    SELECT array(SELECT t2 FROM test_rel WHERE t2='3');

现在,我们尝试使用列t1(具有复合类型的列)执行相同的操作。我现在的问题是,以下情况不起作用:

    SELECT array(SELECT t1 FROM test_rel WHERE t2='3');
    ERROR:  could not find array type for data type compo[]

有人可以给我一个提示,为什么同样的陈述不适用于复合类型?我不仅是stackoverflow的新手,也是PostgreSQL和plpgsql的新手。所以,请告诉我,当我做错事的时候。

1 个答案:

答案 0 :(得分:5)

PostgreSQL mailing list中对此进行了一些讨论。

长话短说,两者都

select array(select array_type from ...)
select array_agg(array_type) from ...

表示数组数组的概念,PostgreSQL不支持。 PostgreSQL支持多维数组,但它们必须是矩形的。 F.ex. ARRAY[[0,1],[2,3]]有效,但ARRAY[[0],[1,2]]不是。

array constructor& 9.5中的array_agg() function

现在,他们明确指出,他们会将数组参数作为多维数组累积,但前提是它的所有部分都具有相同的维度。

  

array()构造函数:如果子查询的输出列是数组类型,则结果将是一个相同类型但一个更高维度的数组;在这种情况下,所有子查询行必须生成具有相同维度的数组,否则结果将不是矩形。

     

array_agg(any array type):输入数组连接成一个更高维度的数组(输入必须都具有相同的维度,不能为空或NULL

对于9.4,你可以将数组包装成row:这样你就可以创建一些几乎 数组数组:< / p>

SELECT array(SELECT ROW(t1) FROM test_rel WHERE t2='3');
SELECT array_agg(ROW(t1)) FROM test_rel WHERE t2='3';

或者,您可以使用recursive CTE(和数组连接)来解决问题,例如:

with recursive inp(arr) as (
  values (array[0,1]), (array[1,2]), (array[2,3])
),
idx(arr, idx) as (
  select arr, row_number() over ()
  from   inp
),
agg(arr, idx) as (
    select array[[0, 0]] || arr, idx
    from   idx
    where  idx = 1
  union all
    select agg.arr || idx.arr, idx.idx
    from   agg
    join   idx on idx.idx = agg.idx + 1
)
select arr[array_lower(arr, 1) + 1 : array_upper(arr, 1)]
from agg
order by idx desc
limit 1;

但当然这个解决方案高度依赖于您的数据(维度)。