我有一个包含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)
。
更多信息:
以下是有效的,但如何更改它以便我不需要指定书籍的所有字段:
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;
答案 0 :(得分:4)
PostgreSQL数组是有用的抽象(非标准,我应该添加),它可以很容易被滥用 - 我认为这正是你想要做的。
您正在尝试使用数组作为NOT规范化数据库模式的借口和快捷方式。它可能适用于一些kludges,但从长远来看这是不值得的。
如果继续使用数组,则无法利用许多真正使SQL有用的结构。例如,您无法有效地在book_set
表中搜索任何给定的作者。
正确的设计是标准化 - book_set
不应包含作者数组。而是创建单独的表authors
和单独的链接表book_author
。
当然,使用规范化方法,插入数据会更加笨拙,查询数据会更加尴尬 - 您需要执行连接。
但是,它可以创建几乎任何可以想象的查询。此外,通过适当的索引,即使您的数据集非常大,它也可以非常快速地工作。