Как импортировать ежедневные данные CSV в таблицу с сгенерированными столбцами postgres

#sql #postgresql #csv #copy

#sql #postgresql #csv #Копировать

Вопрос:

Я новичок в PostgreSQL и ищу некоторые рекомендации и наилучшую практику.

Я создал таблицу путем импорта данных из файла CSV. Затем я изменил таблицу, создав несколько сгенерированных столбцов, подобных этому:

 ALTER TABLE master
ADD office VARCHAR(50)
GENERATED ALWAYS AS (CASE WHEN LEFT(location,4)='Chic' THEN 'CHI'
                     ELSE LEFT(location,strpos(location,'_')-1) END) STORED;
  

Но когда я пытаюсь импортировать новые данные в таблицу, я получаю следующую ошибку:

 ERROR:  column "office" is a generated column
DETAIL:  Generated columns cannot be used in COPY.
  

Моя цель — иметь возможность каждый день импортировать новые данные в таблицу и автоматически заполнять сгенерированные столбцы, чтобы преобразовать данные так, как я хотел. Как я могу это сделать?

Комментарии:

1. Содержат ли ваши импортируемые данные (файл CSV) столбец «office»? Какую команду вы выполняете при импорте новых данных?

2. @Johnny файл CSV не содержит office, office — это сгенерированный столбец на основе столбца «местоположение» в csv. Я просто использую опцию импорта для импорта новых данных, которые, как я полагаю, используют функцию копирования. я мог бы использовать другую функцию, просто не уверен, как

Ответ №1:

 CREATE TEMP TABLE master (location VARCHAR);

ALTER TABLE master
ADD office VARCHAR
GENERATED ALWAYS AS (
    CASE
        WHEN LEFT(location, 4) = 'Chic' THEN 'CHI'
        ELSE LEFT(location, strpos(location, '_') - 1)
    END
) STORED;
                     
--INSERT INTO master (location) VALUES ('Chicago');
--INSERT INTO master (location) VALUES ('New_York');

COPY master (location) FROM $$d:cities.csv$$ CSV;

SELECT * FROM master;
  

Это та структура и поведение, которые вы ожидаете? Если нет, пожалуйста, предоставьте более подробную информацию о структуре вашей таблицы, ваших импортируемых данных и ваших командах импорта.

Кроме того, возможно, при попытке импортировать файл CSV столбцы не связаны должным образом или, возможно, разделитель установлен неправильно. Попробуйте указать каждый столбец в точном порядке, который отображается в вашем файле CSV.

https://www.postgresql.org/docs/12/sql-copy.html

Примечание: d:cities.csv содержит:

 Chicago
New_York
  

Редактировать:

Если позиции столбцов перепутаны между таблицей и csv, может пригодиться следующая операция:

 1. create temporary table tmp (csv_column1 <data_type>, csv_column_2 <data_type>, ...); (including ALL csv columns)
2. copy tmp from '/path/to/file.csv';
3. insert into master (location, other_info, ...) select csv_column_3 as location, csv_column_7 as other_info, ... from tmp;
  

Импорт данных с использованием промежуточной таблицы может немного замедлить работу, но дает вам большую гибкость.

Комментарии:

1. Спасибо! Я думаю, что это близко, но у меня много столбцов в этом csv, местоположение — только один из них. Существуют также дополнительные сгенерированные столбцы. Так должен ли я вызывать каждый столбец конкретно? После попытки выше я получаю следующую ошибку: ОШИБКА: дополнительные данные после последнего ожидаемого контекста столбца: КОПИРОВАНИЕ посещений, строка 1: «col1, col2, col3»

2. Эта ошибка может возникнуть из-за того, что не все столбцы CSV были указаны в команде КОПИРОВАНИЯ или количество столбцов CSV не согласовано во всех строках. Если позиции столбцов перепутаны (сравнение таблицы и файла csv), то я рекомендую выполнить эту операцию в три четких шага, используя временные таблицы (я отредактировал ответ с подробностями). Кроме того, для отладки я бы рекомендовал протестировать csv, тщательно проверив всего несколько строк (1-2), потому что, возможно, CSV содержит строки, неожиданно неправильно отформатированные.

Ответ №2:

Я получал ту же ошибку при импорте в PG из CSV — я обнаружил, что, хотя мой столбец был сгенерирован, он все равно должен был присутствовать в импортированных данных, просто оставил его пустым. Работал нормально, когда имя столбца было там и сопоставлялось с именем моего каталога DB.