2014-12-04 65 views
0

我試圖在具有多個列的架構中通過索引命名來創建新表。通過postgresql中的循環添加多列

CREATE TABLE rflux (pk SERIAL PRIMARY KEY NOT NULL); 

現在我想添加新的列像col0 FLOAT,col1,col2,col3 ....直到colN。

我知道我可以這樣做

ALTER TABLE rflux add column col0 FLOAT add column col1 FLOAT ... ; 

,但我不想一切都打出來,因爲我需要創建〜4500列。我試圖用循環來實現這一點,但我無法完成它的工作。有沒有人有任何想法?我試圖創建一個函數來做到這一點..

create function addColumns() 
returns void 
as $$ 
begin 
for i in 1..10 loop 
alter table rflux add column tmp float; 
alter table rflux rename tmp to col||i; 
end loop; 
return; 
end; 
$$ 
language plpgsql; 

然後做 SELECT * FROM addColumns();

但是,當將列重命名爲col || i時,或甚至當我嘗試i時,我都會遇到錯誤。我甚至不確定這是否是最好的方法。如何添加多列,以便我可以使用計數器增加列的名稱?

編輯..我知道我不能用4500列做這個,但是如果我想爲10列做這個問題,這個問題有什麼解決方法呢?

謝謝。

+0

[每表250的最大列 - 1600根據列類型](http://www.postgresql.org/about/) – 2014-12-04 16:31:16

+0

4500列?我想你可能會考慮重新設計你的模式,而不是把你的糟糕設計帶入數據庫。然而,要做你想做的事,你需要在一個存儲過程中使用「動態SQL」......但你可能不應該這樣做。 – JNevill 2014-12-04 16:41:03

+0

我真正想要的是以某種方式將4500個元素的數組存儲到數據庫中。我可以將它作爲一個float []存儲爲一列,或者每個元素都是一個單獨的列。我關心訪問,並通過SQLAlchemy切片數組。據我所知,postgres將數組存儲爲字符串元素{1,2,3}。當它被SQLAlchemy讀入時,它解析這個字符串並將其轉換爲元素列表。我將擁有數百萬行數據,並且需要過濾行的子集,其中某些數組元素滿足給定的條件。所以我認爲第二種方式會更好。 – havok2063 2014-12-04 18:34:22

回答

0

您的設計可能更適合數組,hstore或json數據類型。添加4500列是等待發生的噩夢。

+0

是的,這聽起來很像,特別是考慮到postgresql中的列限制。你知道這是如何影響在SQLalchemy中甚至在Postgres中爲數百萬行進行這些數組的子集上的過濾效率? – havok2063 2014-12-04 19:23:15

+0

如果你使用的是postgres 9.3,json非常好,你甚至可以索引json對象中的單個數據元素。 如果您使用的版本低於9.3,我會使用hstore並且這些子字段也可以被索引。 有了一個數組,你就失去了命名字段的能力,訂單變得非常重要,所以我個人會避免這種情況。 – 2014-12-04 21:01:21

+0

嗯。好。我使用的是postgres 9.3,所以我會考慮使用JSON和hstore。我不太瞭解他們與數組相比,但如果他們讓我輕鬆地選擇查詢列中的元素的子集,那麼我就是爲了它。謝謝。 – havok2063 2014-12-04 23:50:38

0

如果它可以幫助:

-- VERSION : POSTGRESQL 9.3 

-- FICTIVE TABLE #1 

CREATE TABLE table_1 ("YEAR" int, "CODE_SP" text, "TOTAL" int); 

INSERT INTO table_1 VALUES 
(2035, 'TRUC', 2), 
(2035, 'MUCH', 4), 
(2036, 'FLIC', 7), 
(2036, 'LORD', 2), 
(2036, 'TRUC', 8), 
(2037, 'MUCH', 2), 
(2037, 'FLIC', 2), 
(2037, 'FLAC', 5), 
(2037, 'MORD', 9), 
(2038, 'LOOP', 3), 
(2038, 'MUCH', 3); 

SELECT * FROM table_1; 

-- FICTIVE TABLE #2 

CREATE TABLE table_2 ("YEAR" int); 

INSERT INTO table_2("YEAR") 
SELECT serial 
FROM generate_series(2035,2038,1) AS serial; 

SELECT * FROM table_2; 

-- LOOP FOR ADDING COLUMNS ON TABLE #2 

DO 
$do$ 
    DECLARE colnames TEXT; 
BEGIN 
FOR colnames IN 
    SELECT "CODE_SP" 
    FROM table_1 
    GROUP BY "CODE_SP" 
    ORDER BY "CODE_SP" 
LOOP 
    EXECUTE 'ALTER TABLE table_2 ADD COLUMN ' || quote_ident(colnames) || ' INT DEFAULT NULL;'; /* careful: in quoted text, the spaces are important */ 
END LOOP; 
END 
$do$; 

-- LOOP FOR COMPLETTING CELLS ON TABLE #2 

DO 
$do$ 
    DECLARE id_value TEXT; 
BEGIN 
FOR id_value IN 
    SELECT "CODE_SP" 
    FROM table_1 
    GROUP BY "CODE_SP" 
    ORDER BY "CODE_SP" 
LOOP 
    EXECUTE 'UPDATE table_2 SET ' || quote_ident(id_value) || ' = table_1."TOTAL" FROM table_1 WHERE table_1."CODE_SP" = ' || quote_literal(id_value) || ' AND table_1."YEAR" = table_2."YEAR";'; /* careful: in quoted text, the spaces are important */ 
END LOOP; 
END 
$do$;