简体   繁体   English

通过 postgresql 中的循环添加多列

[英]adding multiple columns via a loop in postgresql

I'm trying to create a new table in a schema that has multiple columns, named via an index.我正在尝试在具有多个列的模式中创建一个新表,这些列通过索引命名。

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

Now I want to add new columns like col0 FLOAT, col1, col2, col3, .... up to colN.现在我想添加新的列,如 col0 FLOAT、col1、col2、col3、.... 直到 colN。

I know I can do something like我知道我可以做类似的事情

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

but I don't want to type everything out, since I need to create ~4500 columns.但我不想输入所有内容,因为我需要创建 ~4500 列。 I'm trying to implement this with loops but I can't quite get it working.我正在尝试用循环来实现它,但我无法让它正常工作。 Does anyone have any ideas?有没有人有任何想法? I've tried creating a function to do this ..我试过创建一个函数来做到这一点..

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;

then do select * from addColumns();然后做 select * from addColumns();

but I get errors when renaming the column to col||i , or even just when I try i.但是在将列重命名为 col||i 时,甚至在我尝试 i 时都会出错。 I'm not even sure if this is the best way to do this.我什至不确定这是否是最好的方法。 How do I add multiple columns where I can increment the name of the column with a counter?如何添加多个列,我可以在其中使用计数器增加列的名称?

Edit..I know I can't do this with 4500 columns, but what's the solution to this problem if I wanted to do it for 10 columns, say?编辑..我知道我不能用 4500 列来做这个,但是如果我想用 10 列来解决这个问题,比如说?

Thanks.谢谢。

your design would likely fit better into an array, hstore, or json data type. 您的设计可能更适合数组,hstore或json数据类型。 Adding 4500 columns is a nightmare waiting to happen. 添加4500列是一场噩梦,等待发生。

If it can help: 如果可以帮助您:

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

One of the additional solutions that I did not find, but created myself.我没有找到但自己创建的其他解决方案之一。

do $$
declare 
    colnames text[];
    target_array text[]:= array[
                                ['table1','product_id'],
                                ['table2','product_id'],
                                ['table3','product_id']
                                ];  
    
begin
   FOREACH colnames SLICE 1 in  ARRAY target_array
   loop
        execute 'alter table '||colnames[1]||' 
                add  '||colnames[2]||' int
                DEFAULT NULL;';
        raise notice 'table: %, column: %', colnames[1], colnames[2];
   end loop;
end; $$;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM