【问题标题】:Postgres - CRUD operations with arrays of composite typesPostgres - 具有复合类型数组的 CRUD 操作
【发布时间】:2020-01-19 16:51:44
【问题描述】:

我刚刚发现的 Postgres 的一个非常简洁的特性是能够定义 composite type - 在他们的文档中也称为 ROWSRECORDS。考虑下面的例子

CREATE TYPE dow_id AS
(
 tslot smallint,
 day smallint
);

现在考虑以下表格

CREATE SEQUENCE test_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 2147483647 START 1 CACHE 1;

CREATE TABLE test_simple_array 
(
 id integer DEFAULT nextval('test_id_seq') NOT NULL,
 dx  integer []
);

CREATE TABLE test_composite_simple 
(
 id integer DEFAULT nextval('test_id_seq') NOT NULL,
 dx  dow_id
);

CREATE TABLE test_composite_array 
(
 id integer DEFAULT nextval('test_id_seq') NOT NULL,
 dx  dow_id[]
);

前两个表的 CRUD 操作相对简单。例如

INSERT INTO test_simple_array (dx) VALUES ('{1,1}');
INSERT INTO test_composite_simple (dx) VALUES (ROW(1,1));

但是,当表具有array of records/composite types(如test_composite_array)时,我无法弄清楚如何执行 CRUD 操作。我试过了

INSERT INTO test_composite_array (dx) VALUES(ARRAY(ROW(1,1),ROW(1,2)));

消息失败

错误:“ROW”处或附近的语法错误

INSERT INTO test_composite_array (dx) VALUES("{(1,1),(1,2)}");

消息失败

错误:列“{(1,1),(1,2)}”不存在

INSERT INTO test_composite_array (dx) VALUES('{"(1,1)","(1,2)"}');

这似乎有效,尽管它让我感到困惑,因为随后

从 test_composite_array 中选择 dx

返回似乎是字符串结果{"(1,1),(1,2)},尽管还有进一步的查询,例如

SELECT id FROM test_composite_array WHERE (dx[1]).tslot = 1;

有效。我也尝试了以下

SELECT (dx[1]).day FROM test_composite_array;
UPDATE test_composite_array SET dx[1].day = 99 WHERE (dx[1]).tslot = 1;
SELECT (dx[1]).day FROM test_composite_array;

同时有效

 UPDATE test_composite_array SET (dx[1]).day = 99 WHERE (dx[1]).tslot = 1;

失败。我发现我正在弄清楚如何通过反复试验来操作 Postgres 中的记录/复合类型数组 - 尽管 Postgres 文档通常非常出色 - 文档中似乎没有明确讨论这个主题。任何人都可以向我指出有关如何在 Postgres 中操作复合类型数组的权威讨论,我将不胜感激。

除此之外,在使用此类数组时是否有任何意外的陷阱?

【问题讨论】:

    标签: arrays postgresql record composite


    【解决方案1】:

    你需要用方括号加上ARRAY:

    ARRAY[ROW(1,1)::dow_id,ROW(1,2)::dow_id]
    

    警告:复合类型是一个很棒的特性,但是如果你过度使用它们会让你的生活变得更加艰难。一旦你想在WHEREJOIN 条件中使用复合类型的元素,你就做错了,你会受苦。对关系数据进行规范化是有充分理由的。

    【讨论】:

    • 谢谢。您暗示使用具有WHERE 条件的复合类型不是一个好主意。你能详细说明一下吗?它会引发什么样的并发症/限制?
    • 感谢指正!只需尝试提出一个SELECT,它会根据dow_id[] 中任何数组元素的一个属性过滤结果。你会发现这样的查询很难写,而且你不能用索引来加速它。
    猜你喜欢
    • 2012-08-09
    • 1970-01-01
    • 2015-06-02
    • 1970-01-01
    • 2020-02-23
    • 1970-01-01
    • 2020-05-01
    • 2013-07-28
    • 2015-03-26
    相关资源
    最近更新 更多