Идеальное решение!
Не нужно знать все столбцы CSV, извлекайте только то, что знаете.
Используйте в SQL CREATE EXTENSION PLpythonU;
: если команда выдает ошибку типа "не удалось открыть файл управления расширением... Нет такого файла", вам необходимо установить дополнительные пакеты pg-py. В стандартном UBUNTU (16 LTS) просто, apt install postgresql-contrib postgresql-plpython
.
CREATE FUNCTION get_csvfile(
file text,
delim_char char(1) = ',',
quote_char char(1) = '"')
returns setof text[] stable language plpythonu as $$
import csv
return csv.reader(
open(file, 'rb'),
quotechar=quote_char,
delimiter=delim_char,
skipinitialspace=True,
escapechar='\\'
)
$$;
INSERT INTO mytable(info)
SELECT jsonb_build_array(c[1],c[2],c[3])
FROM get_csvfile('/tmp/myfile1.csv') c;
Функция split_csv() была определена здесь. csv.reader
очень надежен (!).
Не тестировался для большого-большого CSV... Но ожидается, что Python сделает свою работу.
Обходной путь PostgreSQL
Это не идеальное решение, но оно решает основную проблему, т.
... большая временная таблица, так что потерян процессор, диск и мое время"...
Вот как мы это делаем, обходной путь с file_fdw
!
Примите свои соглашения, чтобы избежать путаницы с копированием файлов и правами доступа к файлам... Стандартный путь к файлу для CSV. Пример: /tmp/pg_myPrj_file.csv
Инициализируйте свою базу данных или сценарий SQL с расширением magic,
CREATE EXTENSION file_fdw;
CREATE SERVER files FOREIGN DATA WRAPPER file_fdw;
Для каждого CSV-файла myNewData.csv
,
3.1. сделать символическую ссылку (или scp
удаленную копию) для вашего нового файла ln -sf $PWD/myNewData.csv /tmp/pg_socKer_file.csv
3.2. настройте file_fdw для вашей новой таблицы (допустим, mytable
).
CREATE FOREIGN TABLE temp1 (a int, b text, c text)
SERVER files OPTIONS (
filename '/tmp/pg_socKer_file.csv',
format 'csv',
header 'true'
);
PS: после запуска SQL-скрипта с psql
при возникновении проблем с правами смените владельца ссылки на sudo chown -h postgres:postgres /tmp/pg_socKer_file.csv
.
3.3. использовать таблицу file_fdw в качестве источника (предположим, заполнить mytable
).
INSERT INTO mytable(info)
SELECT json_build_array(a,b,c) FROM temp1;
Спасибо @JosMac (и его руководству)!
ПРИМЕЧАНИЕ: если есть способ STDIN сделать это (существует??), будет легко, избегая проблем с правами доступа и использования абсолютных путей. См. этот ответ/обсуждение.
person
Community
schedule
04.01.2017