当列数据类型为复合类型时,如何使用PostgreSQL传输数组中的列?
我正在使用PostgreSQL 9.4,目前正在尝试将列值传输到数组中。对于“普通”(非用户定义)数据类型,我可以让它工作 为了详细解释我的问题,我编了一个简单的例子。 假设我们定义一个复合类型“compo”,创建一个表“test_rel”,并插入一些值。看起来像这样,对我有用:当列数据类型为复合类型时,如何使用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
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;