Столбцы csv импорта postgresql изменяются динамически
База данных: PostgreSQL
Мне нужна функция в PL/pgSQL для автоматической загрузки данных в таблицу из файла CSV. Важно: столбцы файла CSV и столбцы целевой таблицы должны быть объявлены.
some_function(data_file_name, table_name, columns_from, columns_to)
ПРИМЕР:
Файл CSV имеет столбцы: A, B, C, D
целевая таблица имеет столбцы: один, два
some_function('file.csv', 'table1', массив ['A', 'B'], массив ['one', 'two'])
Определение массива можно изменить, я не знаю, как передать столбцы, если другой путь.
create or replace function load_csv_procedure
(
csv_path text,
target_table text,
columns_from text[],
columns_to text[]
)
returns void as $$
declare
target_table text;
col_count integer;
iter integer;
col text;
col_first text;
begin
set schema 'public';
create table temp_table ();
col_count := 6;
-- add just enough number of columns
for iter in 1..col_count
loop
execute format('alter table temp_table add column col_%s text;',
iter);
end loop;
-- copy the data from csv file
execute format('copy temp_table from %L with delimiter '','' quote
''"'' csv ', csv_path);
iter := 1;
col_first := (select col_1 from temp_table limit 1);
for col in execute format('select
unnest(string_to_array(trim(temp_table::text, ''()''), '','')) from
temp_table where col_1 = %L', col_first)
loop
execute format('alter table temp_table rename column col_%s to
%s', iter, col);
iter := iter + 1;
end loop;
execute format('delete from temp_table where %s = %L', col_first,
col_first);
--EXECUTE format('INSERT INTO %I (' || columns_to::text || ' ) VALUES
( select (' || columns_from::text || ' ) from temp_table);'::text,
target_table) using columns_to, columns_from;
--
EXECUTE format('INSERT INTO %I (''name'', code ) VALUES (select
DepartmentName, DepartmentCode from temp_table);'::text,
target_table); -- using columns_to, columns_from;
drop table temp_table;
end;
$$ language plpgsql;
1 ответ
Я заставил это работать:)
create or replace function csv_to_table (in target_table text, in
csv_path text, in col_count integer, in columns_from text[], in
columns_to text[])
returns void as $$
declare
iter integer; --dummy integer to iterate with
col text; --dummy variable to iterate with
col_first text; --first column label, e.g., top left corner on a csv
file or spreadsheet
columns_from_str text;
columns_to_str text;
begin
set schema 'public';
drop table if exists temp_table;
create table temp_table ();
-- add just enough number of columns
for iter in 1..col_count
loop
execute 'alter table temp_table add column col_' || iter || '
varchar;';
end loop;
-- copy the data from csv file
execute 'copy temp_table from ''' || csv_path || ''' with delimiter
'',''';
iter := 1;
col_first := (select col_1 from temp_table limit 1);
-- update the column names based on the first row which has the
column names
for col in execute 'select
unnest(string_to_array(trim(temp_table::text, ''()''), '','')) from
temp_table where col_1 = ''' || col_first || ''''
loop
execute 'alter table temp_table rename column col_' || iter || '
to ' || col;
iter := iter + 1;
end loop;
-- delete the columns row
execute 'delete from temp_table where ' || col_first || ' = ''' ||
col_first || '''';
-- make string from all columns
columns_from_str := array_to_string(columns_from, ', ');
columns_to_str := array_to_string(columns_to, ', ');
execute format('insert into %s(%s) select %s from temp_table;',
target_table, columns_to_str, columns_from_str);
end;
$$ language plpgsql;