首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >PostgreSQL中的数组数组

PostgreSQL中的数组数组
EN

Stack Overflow用户
提问于 2012-02-06 19:32:04
回答 3查看 30.2K关注 0票数 6

我在PostgreSQL的hstore类型上使用%%运算符,它将hstore (有效的键值类型)转换为元素交替{ {key,value},{key value}}的数组。

当我想要返回这些扁平化的hstore的数组时,我得到这个错误:由于PostgreSQL缺乏对数组数组的支持而导致的could not find array type for data type text[]

从好奇心的角度来看,有没有人知道为什么不支持这些?更重要的是,对于这种类型的场景,是否有解决方案?

目前,我正在将结果连接成一个字符串(逗号分隔),并在应用程序(C#和NPGSQL端)解析它们。然而,这种方法感觉不太正确,我希望能够将行读回为数组的.NET数组或键值数组等。

非常感谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-02-08 06:25:08

从好奇心的角度来看,有没有人知道为什么不支持这些?

一个通用的答案是因为数组本质上是反关系的。删除重复值是实现1st normal form的方法。从关系理论的角度来看,拥有重复组的重复组似乎是相当疯狂的。

一般来说,关系正确的做法是为重复的值提取一个表。所以如果你做了这样的建模:

代码语言:javascript
运行
复制
CREATE TABLE users (
  id integer primary key,
  name varchar,
  favorite_colors varchar[],
  ...
);

你应该像这样重新定义这种关系:

代码语言:javascript
运行
复制
CREATE TABLE users (
  id integer primary key,
  name varchar,
  ...
);

CREATE TABLE favorite_colors (
  user_id integer references users,
  color varchar
);

或者甚至是:

代码语言:javascript
运行
复制
CREATE TABLE users (
  id integer primary key,
  name varchar,
  ...
);

CREATE TABLE colors (
  color varchar primary key
);

CREATE TABLE favorite_colors (
  user_id integer references users,
  color varchar references colors,
  primary key (user_id, color)
);

Hstore支持许多函数,其中许多函数可以很容易地将其集成到关系世界观中。我认为解决问题的最简单方法是使用each函数将hstore值转换为关系,然后可以像使用一组普通值一样使用它们。这就是如何解决在其他数据库中有多个值的问题:查询和处理结果集。

票数 8
EN

Stack Overflow用户

发布于 2012-05-09 22:33:30

PostgreSQL对“数组数组”的支持有限

see manual

它是“数组的数组”的一种受限形式。正如Pavel (answer)所说,它被命名为“多维数组”,但实际上是一个矩阵,因此它在每个维度上必须有相同数量的元素。

在科学应用程序中,您可以将这种结构用于映射多维和异构笛卡尔坐标,但不能像XML或JSON数据那样存储任意向量的向量。

注意:众所周知的二维(2D)均匀数组是mathematical matrix。事实上,激发"PostgreSQL constrained多维数组“数据类型的矩阵的科学应用,以及数组函数与这些类型的数组的行为。将"3D数组“视为"3D矩阵”,将"4D数组“视为"4D矩阵”,以此类推。

示例:

代码语言:javascript
运行
复制
SELECT array_cat(ARRAY[[1,2],[3,4]], ARRAY[5,6]);
---------------------
 {{1,2},{3,4},{5,6}}
SELECT array_cat(ARRAY[[1,2],[3,4]], ARRAY[[5,6]]); -- SAME RESULT

SELECT ARRAY[ARRAY[1,2],ARRAY[5,6]];
---------------
 {{1,2},{5,6}}

SELECT array_cat(ARRAY[ARRAY[1,2]],ARRAY[3]); -- ERROR1
SELECT ARRAY[ARRAY[1,2],ARRAY[4]];  -- ERROR2 

@Daniel_Lyons关于“为什么不支持这些”的评论是关于“非均匀数组”的(参见上面的错误案例)。上面的ERROR1:因为上面的ERROR2只能连接相同维度的数组:特定维度的所有数组必须具有相同的长度,就像矩阵一样。

关于内置函数和运算符的另一件奇怪的事情是: PostgreSQL中的“默认行为”是针对单个数组和元素的。标准array_append()没有重载,

代码语言:javascript
运行
复制
SELECT array_append(ARRAY[1,2],5); -- now ok, 5 is a element
 {1,2,5}

SELECT array_cat(ARRAY[1,2], ARRAY[5,6]);
----------
 {1,2,5,6}

SELECT array_append(ARRAY[[1,2],[3,4]], ARRAY[5,6]); -- ERROR3 
SELECT array_append(ARRAY[1,2],ARRAY[5,6]); -- ERROR4

上面的ERROR3:没有重载来追加“数组元素”(即使是9.2PG版本)。上面的ERROR4:必须使用array_cat来“将所有内容合并到一个数组中”。

最后一个array_cat示例的“合并行为”很奇怪,没有生成数组的数组。使用array_cat(a1, ARRAY[a2])来实现此结果,

代码语言:javascript
运行
复制
SELECT array_cat(ARRAY[1,2], ARRAY[ARRAY[5,6]]);  -- seems illogical...
---------------
{{1,2},{5,6}}

稀疏矩阵

为了避免sparse matrix和类似数据结构出现问题,请使用下面的函数。它填充其余元素,然后将其设置为NULL (或任何常量值)。

代码语言:javascript
运行
复制
 CREATE or replace FUNCTION array_fillTo(
    p_array anyarray, p_len integer, p_null anyelement DEFAULT NULL
 ) RETURNS anyarray AS $f$
   SELECT CASE 
       WHEN len=0 THEN array_fill(p_null,array[p_len])
       WHEN len<p_len THEN p_array || array_fill($3,array[$2-len])
       ELSE $1 END
   FROM ( SELECT COALESCE( array_length(p_array,1), 0) ) t(len)
 $f$ LANGUAGE SQL IMMUTABLE;

PS:请编辑此答案以添加任何更正/优化,它是一个Wiki!

返回到第一个示例,现在我们可以避免错误(参见ERROR1),

代码语言:javascript
运行
复制
SELECT array_cat(ARRAY[ARRAY[1,2]],array_fillTo(ARRAY[3],2));
-- {{1,2},{3,NULL}}
SELECT array_cat(
   ARRAY[ARRAY[1.1::float,2.0]],
   array_fillTo(ARRAY[]::float[],2,0::float)
);
-- {{1.1,2},{0,0}}
SELECT array_fillto(array['Hello'],2,'');
-- {Hello,""}

关于旧的array_fillTo()的说明

对于v8.3或更早版本,array_fill()将成为PostgreSQL v8.4的内置函数:

代码语言:javascript
运行
复制
 CREATE FUNCTION array_fillTo(anyarray,integer,anyelement DEFAULT NULL) 
 RETURNS anyarray AS $$
   DECLARE
     i integer;
     len integer;
     ret ALIAS FOR $0;
   BEGIN
     len = array_length($1,1);
     ret = $1;
     IF len<$2 THEN
         FOR i IN 1..($2-len) LOOP
           ret = ret || $3;
         END LOOP;
     END IF;
     RETURN ret;
   END;
 $$ LANGUAGE plpgsql IMMUTABLE;
票数 21
EN

Stack Overflow用户

发布于 2012-02-08 05:56:47

相反,PostgreSQL支持多维数组-在关系数据库中,数组是相对非常特殊的类型,与一般编程语言相比,它有一点限制。如果需要,可以使用行数组的变通方法:

代码语言:javascript
运行
复制
postgres=# create table fx(a int[]);
CREATE TABLE
postgres=# insert into fx values(array[1,3,4]);
INSERT 0 1
postgres=# insert into fx values(array[6,7]);
INSERT 0 1
postgres=# select array_agg(row(a)) from fx;
            array_agg            
---------------------------------
 {"(\"{1,3,4}\")","(\"{6,7}\")"}
(1 row)
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9159440

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档