错误:COPY分隔符必须是单个单字节字符

时间:2011-08-03 17:00:06

标签: postgresql postgresql-copy

我想将带有分隔符“〜,〜”的平面文件中的数据加载到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 个答案:

答案 0 :(得分:7)

如果您使用的是Vertica,则可以使用E'\ t'或U&'\ 0009'

  

表示非打印分隔符(例如制表符),   在扩展字符串语法(E'...')中指定字符。如果你的   数据库启用了StandardConformingStrings,使用Unicode字符串   文字(U&'...')。例如,使用E'\ t'或U&'\ 0009'来   将制表符指定为分隔符。

答案 1 :(得分:3)

不幸的是,没有办法在Postgres中加载带有多个字符分隔符~,~的平面文件,除非您想以某种(非常好的)方式自行修改source code(并重新编译):

/* 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

答案 2 :(得分:3)

显而易见的事情是所有其他答案所建议的。编辑导入文件。我也会这样做。

但是,作为概念验证,有两种方法可以在没有其他工具的情况下完成此

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)特殊情况

如果,您可以保证'〜'仅出现在分隔符'〜,〜'中,那么您可以在这种特殊情况下继续使用普通COPY。只需将'〜,'中的','视为附加列。 说,你的表看起来像这样:

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 :(得分:1)

不确定您是在寻找postgresql解决方案还是只是一般解决方案。

如果是我,我会打开vim(或gvim)的副本并运行推荐:%s/~,~/~/g
用“〜”替换所有“〜,〜”。

答案 4 :(得分:0)

您可以使用单个字符分隔符,打开notepadctrl+h替换~,~,不会有任何干扰。比如|