2013-01-08 63 views
3

我有一個包含TEXT等數組的複合類型。我在我的主表中使用這個來創建一個複合類型的數組。
如何生成INSERT命令(不使用複合類型的默認字段名稱)?我可以用組合數組創建一個TEMPORARY TABLE,然後將它插入到主表中嗎?PostgreSQL - 插入一個包含數組的複合類型數組

例如:

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); 

所述第一插入失敗,並在消息:

ERROR: INSERT has more expressions than target columns.

失敗相同具有或不具有陣列[]構造。

我的現實世界的用法顯然更復雜,包含其他複合材料的複合材料以及許多領域。

由於性能方面的原因,我沒有使用多個表(不需要連接來檢索),內部組合和數組也不會獨立引用。

我使用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

歡迎來到StackOverflow!在這一點上,它看起來不像使用Perl DBI,所以這真的是PostgreSQL的問題,對吧?如果您不使用[數組類型](http://www.postgresql.org/docs/current/static/arrays.html「看起來很有用!」),SQL是否工作? –

+0

哦。當你說「它還沒有工作」時,你是否有錯誤信息?你能複製它並粘貼在問題中嗎? –

+0

在學習複合類型之前,我已經完成了整個解決方案。但是做複合材料的INSERT,尤其是包含數組的composites數組讓我感到困惑。並且錯誤消息是:錯誤:INSERT具有比目標列更多的表達式 –

回答

4

PostgreSQL的數組是有用的抽象(非標準的,我應該補充),它可以很容易被濫用 - 我想這正是你想要做的。

您正試圖使用​​數組作爲藉口和快捷方式來規範化數據庫模式。它可能適用於一些問題,但從長遠來看,這是不值得的。

如果你繼續使用數組,你將無法利用許多真正使SQL有用的構造。例如,您無法有效搜索您的book_set表中的任何給定作者。

正確的設計將正常化 - book_set不應該包含作者數組。相反,創建單獨的表authors和單獨的鏈接表book_author

當然,使用規範化的方法,插入數據會更尷尬,而查詢它更笨拙 - 您將需要執行連接。

但是,它幾乎可以創建任何可以想象的查詢。而且,通過適當的索引,即使數據集非常大,它也可以非常快速地工作。

+0

謝謝mvp。我明白你的迴應。但是,在我的實際案例中,出於性能方面的原因,我確實不想要一個單獨的表。一旦我從主表執行SELECT操作,我需要數組在那裏,而不必與其他關聯的I/O進行連接。我明白陣列中的數據不可搜索,但這不是問題。大部分數據已經從其他表中複製過來,並且在那裏(重複)的性能。 –

+1

你可能沒有意識到它,但是如果你的數組大於某個閾值,Postgres將不得不將數據卸載到隱形的TOAST表(它被分成固定大小的塊並與主表連接)。這是同樣的加入,但沒有你控制它。真正的加入 - 他們不一定很慢,如果你做對了 – mvp

+0

PS:我從一個規範化的數據庫開始,但結束了9個連接,以獲得我主要的大量查詢數據。 –