2014-12-04 2 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

[Maximum колонок в таблице 250 - 1600 в зависимости от типов столбцов] (http://www.postgresql.org/about/) –

+0

4500 Колонны ?? Я думаю, вы можете подумать о том, чтобы перепроектировать вашу схему, а не обучать ваш плохой дизайн в вашей БД. Однако, чтобы делать то, что вы хотите, вы захотите использовать «динамический SQL» в хранимой процедуре ... но вы, вероятно, не должны этого делать. – JNevill

+0

Что я на самом деле хочу, так это хранить массивы 4500 элементов в базе данных. Я могу сохранить его как один столбец как float [] или где каждый элемент является отдельным столбцом. Меня беспокоит доступ и разбиение массива с помощью SQLAlchemy. Насколько я понимаю, postgres хранит массивы в виде строковых элементов {1,2,3}. Когда это считывается SQLAlchemy, он анализирует эту строку и преобразует ее в список элементов. У меня будет миллионы строк данных, и вам нужно будет фильтровать подмножества строк, где определенные элементы массивов удовлетворяют заданному условию. Поэтому я подумал, что второй способ будет лучше. – havok2063

ответ

0

Ваш дизайн, скорее всего, будет лучше соответствовать массиву, hstore или json. Добавление 4500 колонок - это кошмар, ожидающий своего появления.

+0

Да, это то, на что это похоже, особенно учитывая ограничения столбцов в postgresql. У вас есть идея, как это влияет на эффективность фильтрации на подмножествах этих массивов для миллионов строк в SQLalchemy или даже в postgres? – havok2063

+0

Если вы используете postgres 9.3, json довольно хорош, и вы даже можете индексировать отдельные элементы данных в объекте json. Если вы используете версию менее 9,3, я бы пошел с hstore, и эти подполя также могут быть проиндексированы. С массивом вы теряете способность называть свои поля и порядок, становится чрезвычайно важным, поэтому лично я бы избегал этого сценария. –

+0

Хммм. ОК. Я использую postgres 9.3, поэтому я изучу использование JSON и hstore.Я не знаю много о них по сравнению с массивами, но если они позволяют мне легко выбирать подмножества элементов в столбцах в запросах, то я все для этого. Благодарю. – havok2063

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$; 
Смежные вопросы