Обзор:
1) У меня есть дамп .TSV [значения, разделенные табуляцией, плоский файл], который мне нужно шунтировать в существующую таблицу Postgres [таблица не моего дизайна, но у меня есть прямойdb access] Я намерен использовать psql \ copy для этого;
2) В рассматриваемой таблице один столбец определен как одномерный массив [исторические причины, которые я не контролирую;я знаю, что денормализованные столбцы в большинстве случаев далеки от оптимальных.]
3) В TSV пятый столбец содержит значения, предназначенные для столбца массива Postgres;эти значения разделены запятыми
4) Чтобы получить эти значения в столбце массива postgres, я считаю, что мне нужно обернуть их следующим шаблоном: ‘{}’
- таким, что значения: foo,bar
стать ‘{foo,bar}’
Я предполагаю, что лучший способ сделать это с помощью регулярных выражений, но мои навыки в этой области в настоящее время очень слабы [работаю над этим, имейте книгу совы и поваренную книгу регулярных выражений! ]. Я прочитал несколько связанных SO / вопросов / ответов, просмотрел rexegg и regex101, но не могу найти здесь или в другом месте информацию, которая описывает достаточно похожую ситуацию, чтобы я мог использовать в ней решения / подходы.
Есть несколько конкретных аспектов этой проблемы, на которых я застрял:
a) Поскольку данные в каждом столбце имеют переменную длину [то есть каждое значение может быть любой длины],Я не могу понять, как определить пятую колонку [чтобы действовать в соответствии с ней];
b) Точно так же мне нужно добавить '{к началу столбца и}' к его концу, но, поскольку данные в столбце изменчивы по содержанию и длине, я не могу понять,как с этим справиться - например, я не могу сказать регулярному выражению искать какой-либо конкретный символ или длину, чтобы вызвать добавление скобок / кавычек в правильной позиции
Ниже приведен пример строки изфайл .tsv;пятый столбец с запятой, разделяющей два значения, - это то, над чем я пытаюсь действовать.
1234 e@mail.addy 43210 0123456789 foo_value,bar_value 107.00 0.00 timestamp_1 timestamp_2 54321 string_2 string_3 timestamp_3 98765 12345 US Hawaii string_4 string_5 string_6 string_7 string_8 false true false
когда регулярное выражение [или любое другое преобразование работает] выполнено с ним, оно должно [я думаю] выглядеть следующим образом:
1234 e@mail.addy 43210 0123456789 ’{foo_value,bar_value}’ 107.00 0.00 timestamp_1 timestamp_2 54321 string_2 string_3 timestamp_3 98765 12345 US Hawaii string_4 string_5 string_6 string_7 string_8 false true false
, чтобы столбец массива Postgres распозналвход как действительный массив.
Вот определение таблицы Postgres:
CREATE TABLE postgres_table (
col1 SERIAL PRIMARY KEY,
col2 TEXT,
col3 TEXT,
col4 TEXT,
col5 TEXT[], /*this is the array column*/
col6 NUMERIC(19,2) NOT NULL,
col7 NUMERIC(19,2),
col8 TIMESTAMP WITHOUT TIME ZONE,
col9 TIMESTAMP WITHOUT TIME ZONE,
col10 TEXT,
col11 TEXT,
col12 TEXT,
col13 TIMESTAMP WITHOUT TIME ZONE DEFAULT now(),
col14 TEXT,
col15 TEXT,
col16 TEXT,
col17 TEXT,
col18 TEXT,
col19 TEXT,
col20 TEXT,
col21 TEXT,
col22 TEXT,
col23 BOOLEAN,
col24 BOOLEAN,
col25 BOOLEAN
);
дополнительные примечания: db - это Postgres 11;все задействованные системы основаны на RHEL;Я немного знаю JavaScript и SQL, но мои попытки до сих пор были в bash, я успешно использовал \ copy для многих дампов типа .csv в прошлом [но никогда в денормализованную таблицу], и я подумал, что нижеТаким образом, вопрос мог бы получить большую часть пути, но я получаю ошибку “substitution failed”
, когда пытаюсь адаптировать решение к моей ситуации: Как я могу получить все данные из определенного столбца?
Чтобы уточнить: я стремлюсь использовать любой подход, который работает, поэтому, если есть лучший способ сделать это, чем регулярное выражение, я весь слух! Все рекомендации очень ценятся.
РЕДАКТИРОВАТЬ:
Большое спасибо @James Brown и @jjanes - мне еще не хватает «очков репутации», чтобы поднять ваши ответы, но я обязательно сделаю этокак только смогу.
Решение awk от @James Brown ниже работало для меня - обработанный файл содержал завершающий перевод строки, который мне пришлось запрограммировать на сценарий awk из этого unix.SE вопрос: https://unix.stackexchange.com/questions/140727/how-can-i-delete-a-trailing-newline-in-bash
Я рад, что у меня появился стимул, чтобы выучить еще несколько awk;какой отличный инструмент.
ОБНОВЛЕНИЕ: Я все еще работаю над тем, чтобы решение @jjanes работало для моего собственного назидания - все еще сталкиваюсь с проблемами разрешений после подхода GRANT TEMP, но я подозреваю, что это как-то связано с тем, как RDS [гдебаза данных размещена] обрабатывает удаленные запросы psql - обновится снова, когда он у меня будет работать // - я попробовал решение @jjanes ниже, но столкнулся со следующей проблемой на шаге \copy
: ERROR: permission denied for schema pg_temp_5
вот вывод \z pg_temp_5.*
: Access privileges
Schema | Name | Type | Access privileges | Column access privileges
-----------+--------+-------+-------------------+--------------------------
pg_temp_5 | foobar | table | user1=arwdDxt/user1 |
Я пробовал: GRANT USAGE ON SCHEMA pg_temp_5 TO user1;
GRANT ALL ON SCHEMA pg_temp_5 TO user1;
ALTER TABLE pg_temp_5.foobar OWNER TO user1;
, как предложено в следующемg SF вопрос, но без игры в кости https://serverfault.com/questions/488669/postgres-insert-error-permission-denied-for-schema-public
Я не вижу причин, почему это не должно сработать, настоящий скребок головы.