Как импортировать csv файл в postgres и разбить его на несколько таблиц

я пытаюсь импортировать данные из scv в postgres с помощью psql на отдаленном ubuntu сервере и проблема в том что я не знаю как их разбить на 2 таблицы со связкой ManyToOne


Ответы (1 шт):

Автор решения: Ainar-G

Самый простой вариант — это просто свалить все данные в одну таблицу и разгрести оттуда отдельными командами. Очень рекомендую этот вариант, если ресурсы позволяют. Если нет, можно устроить адскую машинерию из вьюх, триггеров, и прочего безобразия:

  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
    )
    ;
  2. Предположим следующий формат данных (ID 1 таблицы, ID 2 таблицы, данные для 2 таблицы):

    1,1,101
    1,2,102
    2,3,201
  3. Создаём вьюху:

    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);
  4. Создаём функцию триггера:

    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;
             $$;
  5. Создаём триггер:

     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);
  6. Копируем:

    COPY t_1_and_t_2_view(t_1_id, t_2_id, t_2_v)
    FROM '/tmp/data.csv'
    WITH DELIMITER ',';
  7. Долго думаем, стоит ли оно всё того :-) .

Фидель (очевидно не заработает на сайте, ибо COPY): https://www.db-fiddle.com/f/vY4Ho5jsaZG9iVx4oUqPrr/0.

→ Ссылка