Как импортировать csv файл в postgres и разбить его на несколько таблиц
я пытаюсь импортировать данные из scv в postgres с помощью psql на отдаленном ubuntu сервере и проблема в том что я не знаю как их разбить на 2 таблицы со связкой ManyToOne
Ответы (1 шт):
Самый простой вариант — это просто свалить все данные в одну таблицу и разгрести оттуда отдельными командами. Очень рекомендую этот вариант, если ресурсы позволяют. Если нет, можно устроить адскую машинерию из вьюх, триггеров, и прочего безобразия:
-
Предположим следующую схему из двух таблиц:
CREATE TABLE IF NOT EXISTS t_1 ( t_1_id INTEGER PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY ) ; CREATE TABLE IF NOT EXISTS t_2 ( t_2_id INTEGER PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY , t_1_id INTEGER REFERENCES t_1(t_1_id) , t_2_v INTEGER ) ; -
Предположим следующий формат данных (ID 1 таблицы, ID 2 таблицы, данные для 2 таблицы):
1,1,101 1,2,102 2,3,201 -
Создаём вьюху:
CREATE TEMPORARY VIEW t_1_and_t_2_view AS SELECT t_1.t_1_id, t_2.t_2_id, t_2.t_2_v FROM t_1 LEFT JOIN t_2 USING (t_1_id); -
Создаём функцию триггера:
CREATE OR REPLACE FUNCTION fill_t_1_and_t_2() RETURNS TRIGGER LANGUAGE PLPGSQL AS $$ BEGIN INSERT INTO t_1 (t_1_id) VALUES (NEW.t_1_id) ON CONFLICT (t_1_id) DO NOTHING; INSERT INTO t_2 (t_2_id, t_1_id, t_2_v) VALUES (NEW.t_2_id, NEW.t_1_id, NEW.t_2_v) ON CONFLICT (t_2_id) DO NOTHING; RETURN NEW; END; $$; -
Создаём триггер:
CREATE TRIGGER t_1_and_t_2_view_insert_trigger INSTEAD OF INSERT ON t_1_and_t_2_view FOR EACH ROW EXECUTE FUNCTION fill_t_1_and_t_2(t_1_id, t_2_id, t_2_v); -
Копируем:
COPY t_1_and_t_2_view(t_1_id, t_2_id, t_2_v) FROM '/tmp/data.csv' WITH DELIMITER ','; -
Долго думаем, стоит ли оно всё того :-) .
Фидель (очевидно не заработает на сайте,
ибо COPY):
https://www.db-fiddle.com/f/vY4Ho5jsaZG9iVx4oUqPrr/0.