我有一个包含TEXT等数组的复合类型。我在主表中使用它来创建复合类型的数组。 如何生成INSERT命令(不使用复合类型的默认字段名称)?我可以使用复合数组创建一个TEMPORARY TABLE,然后将其插入主表吗?
例如:
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 );
第一个INSERT失败,并显示以下消息:
错误:INSERT具有比目标列更多的表达式。
有或没有array []构造都失败。
我的实际使用情况要复杂得多,因为该复合材料包含其他复合材料以及许多其他领域。
出于性能原因,我在这里不使用多个表(无需连接即可检索),并且内部组合和数组从不独立引用。
我正在使用perl(5.14.2)和DBI(1.616)和psql(9.1.7)。
perl(5.14.2)
DBI(1.616)
psql(9.1.7)
更多信息:
下面的作品,但是我如何更改它,这样我就不必指定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数组是有用的抽象(非标准,我应该添加),有点容易被滥用-我认为这正是您要尝试的方法。
您正在尝试使用数组作为不规范数据库架构的借口和捷径。它可能适用于某些问题,但从长远来看,这是不值得的。
如果继续使用数组,将无法利用许多确实使SQL有用的构造。例如,您不能有效地在book_set表中搜索任何给定的作者。
book_set
正确的设计将是规范化的-book_set不应包含大量作者。而是创建单独的表authors和单独的链接表book_author。
authors
book_author
当然,使用规范化方法插入数据更麻烦,查询数据也更麻烦-您将需要执行联接。
但是,这使得创建几乎所有可以想象的查询成为可能。同样,通过适当的索引编制,即使您的数据集非常大,它也可以非常快速地工作。