简体   繁体   English

PostgreSQL - INSERT包含数组的复合类型数组

[英]PostgreSQL - INSERT an array of composite type containing arrays

I have a composite type containing arrays of TEXT, etc. I am using this inside my main table to create an array of composite type. 我有一个包含TEXT等数组的复合类型。我在我的主表中使用它来创建一个复合类型的数组。
How do I generate an INSERT command (without using the default field names of the composite type) ? 如何生成INSERT命令(不使用复合类型的默认字段名称)? Can I create a TEMPORARY TABLE with the array of composites and then insert it into the main table? 我可以使用复合数组创建TEMPORARY TABLE,然后将其插入主表吗?

For example: 例如:

DROP TABLE collection;
DROP TABLE book_set;
DROP TYPE book;

CREATE TYPE book AS ( title TEXT, authors TEXT[], extra_spare TEXT );
CREATE TEMPORARY TABLE book_set ( books book[] );
CREATE TABLE shelf_collection ( shelf INT, position INT, books book[] );

-- Prefer to specify the fields I want, and NOT extra_spare as shown here!
-- AND it doesn't yet work... needs more casting?
INSERT INTO book_set( books ) VALUES (
      ( 'book1', array[ ( 'author1', 'author2' ) ], '' ),
      ( 'book2', array[ ( 'author3' )            ], '' ) ); 

-- And this obviously does not work yet!
INSERT INTO shelf_collection( shelf, position, books ) VALUES ( 1, 2, book_set ); 

The first INSERT fails with the message: 第一个INSERT失败并显示以下消息:

ERROR: INSERT has more expressions than target columns. 错误:INSERT的表达式多于目标列。

Fails same with or without array[] construct. 有或没有array []构造失败。

My real-world usage is significantly more complex, with the composite containing other composites, and many many fields. 我的实际使用情况要复杂得多,包含其他复合材料的复合材料以及许多领域。

I am not using multiple tables here for performance reasons (no join required to retrieve), and the inner composites and arrays are never referenced independently. 出于性能原因,我没有在这里使用多个表(不需要连接来检索),并且内部组合和数组永远不会独立引用。

I am using perl(5.14.2) and DBI(1.616) and psql(9.1.7) . 我使用的是perl(5.14.2)DBI(1.616)以及psql(9.1.7)


MORE INFO: 更多信息:

The following works, but how do I change it so that I do not need to specify ALL fields of book: 以下工作,但如何更改它,以便我不需要指定书的所有字段:

DROP TABLE shelf_collection;
DROP TYPE book;

CREATE TYPE  book AS          ( title TEXT, authors TEXT[], extra_spare TEXT );
CREATE TABLE shelf_collection ( shelf INT, position INT, books book[] );

INSERT INTO shelf_collection VALUES ( 12, 23, array[ROW( 'book title 1', array[ 'author1', 'author2' ], '' )::book] );

SELECT * FROM shelf_collection;

PostgreSQL arrays are useful abstraction (non-standard, I should add), bit it can be easily abused - and I think this is exactly what you are trying to do. PostgreSQL数组是有用的抽象(非标准,我应该添加),它可以很容易被滥用 - 我认为这正是你想要做的。

You are trying to use arrays as an excuse and shortcut to NOT normalize your database schema. 您正在尝试使用数组作为不规范化数据库模式的借口和快捷方式。 It may work with some kludges, but this is not worth it in the long run. 它可能适用于一些kludges,但从长远来看这是不值得的。

If you continue to use arrays, you will not be able to take advantage of many constructs which really make SQL useful. 如果继续使用数组,您将无法利用许多真正使SQL有用的结构。 For example, you cannot effectively search your book_set table for any given author. 例如,您无法有效地在book_set表中搜索任何给定的作者。

Right design would be to normalize - book_set should not contain array of authors. 正确的设计是规范化 - book_set不应该包含作者数组。 Instead, create separate table authors and separate link table book_author . 而是创建单独的表authors和单独的链接表book_author

Granted, with normalized approach it is more awkward to insert data, and somewhat more awkward to query it - you will need to perform joins. 当然,使用规范化方法,插入数据会更加笨拙,而查询数据会更加尴尬 - 您需要执行连接。

But, it makes possible to create almost any query imaginable. 但是,它可以创建几乎任何可以想象的查询。 Also, with proper indexing it makes it work very fast even it your data set is extremely large. 此外,通过适当的索引,即使您的数据集非常大,它也可以非常快速地工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM