ОШИБКА: разделитель COPY должен быть однобайтовым символом - PullRequest
6 голосов
/ 03 августа 2011

Я хочу загрузить данные из плоского файла с разделителем "~, ~" в таблицу PostgreSQL.Я пробовал это, как показано ниже, но похоже, что есть ограничение для разделителя.Если оператор COPY не допускает использование нескольких символов для разделителя, есть ли альтернатива для этого?

metadb=# \COPY public.CME_DATA_STAGE_TRANS FROM 'E:\Infor\Outbound_Marketing\7.2.1\EM\metadata\pgtrans.log' WITH      DELIMITER AS '~,~'
ERROR:  COPY delimiter must be a single one-byte character
\copy: ERROR:  COPY delimiter must be a single one-byte character

Ответы [ 5 ]

8 голосов
/ 26 августа 2015

Если вы используете Vertica , вы можете использовать E '\ t'or U &' \ 0009 '

Для обозначения непечатаемого символа разделителя (напримерtab), укажите символ в расширенном строковом синтаксисе (E '...').Если в вашей базе данных включена функция StandardConformingStrings, используйте строковый литерал Unicode (U & '...').Например, используйте E '\ t' или U & '\ 0009', чтобы указать табуляцию в качестве разделителя.

3 голосов
/ 09 октября 2011

Очевидная вещь, которую нужно сделать, - это то, что советовали все остальные ответы.Редактировать файл импорта.Я бы тоже это сделал.

Однако, в качестве подтверждения концепции, есть два способа сделать это без дополнительных инструментов .

1) Общее решение

CREATE OR REPLACE FUNCTION f_import_file(OUT my_count integer)
  RETURNS integer AS
$BODY$
DECLARE
    myfile    text;  -- read xml file into that var.
    datafile text := '\path\to\file.txt'; -- !pg_read_file only accepts relative path in database dir!
BEGIN

myfile := pg_read_file(datafile, 0, 100000000);  -- arbitrary 100 MB max.

INSERT INTO public.my_tbl
SELECT ('(' || regexp_split_to_table(replace(myfile, '~,~', ','), E'\n') || ')')::public.my_tbl;

-- !depending on file format, you might need additional quotes to create a valid format.

GET DIAGNOSTICS my_count = ROW_COUNT;

END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

Это использует ряд довольно продвинутых функций.Если кто-то действительно заинтересован и нуждается в объяснении, оставьте комментарий к этому сообщению, и я уточню.

2) Особый случай

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

CREATE TABLE foo (a int, b int, c int);

Тогда вы можете (за одну транзакцию):

CREATE TEMP TABLE foo_tmp ON COMMIT DROP (
 a int, tmp1 "char"
,b int, tmp2 "char"
,c int);

COPY foo_tmp FROM '\path\to\file.txt' WITH DELIMITER AS '~';

ALTER TABLE foo_tmp DROP COLUMN tmp1;
ALTER TABLE foo_tmp DROP COLUMN tmp2;

INSERT INTO foo SELECT * FROM foo_tmp;
3 голосов
/ 10 августа 2011

К сожалению, в Postgres нет способа загрузить плоский файл с разделителем из нескольких символов ~,~, если вы не хотите самостоятельно (* потрясающе) каким-либо (потрясающим) образом изменить исходный код (и, конечно, перекомпилировать) самостоятельно.1004 *

/* Only single-byte delimiter strings are supported. */
if (strlen(cstate->delim) != 1)
    ereport(ERROR,
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    errmsg("COPY delimiter must be a single one-byte character")));

Вам нужно препроцессировать ваш входной файл с помощью какого-либо внешнего инструмента, например sed может быть лучшим компаньоном на платформе GNU / Linux, например:

sed s/~,~/\\t/g inputFile
1 голос
/ 03 августа 2011

Не совсем уверен, если вы ищете решение postgresql или просто общее решение.

Если бы это был я, я бы открыл копию vim (или gvim) и выполнил команду :%s/~,~/~/g
Это заменяет все "~, ~" на "~".

0 голосов
/ 03 августа 2011

вы можете использовать один символ разделителя, откройте notepad нажмите ctrl+h заменить ~,~ что-то не помешает. как |

...