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

当列数据类型为复合类型时,如何使用PostgreSQL传输数组中的列?,sql,postgresql,plpgsql,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_re

我正在使用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。所以,请告诉我,当我做错事的时候。

有一些关于这方面的讨论

长话短说

select array(select array_type from ...)
select array_agg(array_type) from ...
表示数组数组的概念,PostgreSQL不支持该概念。PostgreSQL支持多维数组,但它们必须是矩形的。F.ex<代码>数组[[0,1],[2,3]]有效,但
数组[[0],[1,2]]]
无效

9.5中的和都有一些改进

现在,他们明确声明,他们将把数组参数作为多维数组进行累加,但前提是它的所有部分都具有相同的维度

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

array\u agg(任何数组类型)
:输入数组连接到一个更高维度的数组中(输入必须具有相同的维度,并且不能为空或
NULL

对于9.4,您可以将数组包装成
:通过这种方式,您可以创建一些东西,它几乎是一个数组数组:

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

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;

当然,此解决方案高度依赖于数据的维度。

如果需要选择复合类型的数组,这几乎肯定意味着数据库模型设计不当,需要完全重建。因为之前的错误决定,你已经走到了死胡同,不要浪费时间,你绝对是对的。我的数据库模型很糟糕,因为它甚至没有使用第一个范式。但在我的例子中,这(听起来很愚蠢)是正确的,因为我的任务是为大学实现一个非第一范式模型(NF2)。我试图使它尽可能的通用,而不是绑定到覆盖应用程序,现在,在这一点上,卡住了?
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;