Postgresql COPY,文本值包含\ 0(反斜杠0)

时间:2015-02-13 16:16:58

标签: postgresql text escaping psql backslash

设置:Postgresql Server 9.3 - 操作系统:CentOS 6.6

尝试使用COPY命令将2.5亿条记录批量插入Postgresql 9.3服务器。数据采用分隔格式,使用管道' |'作为分隔符。

我复制到的表中几乎所有列都是TEXT数据类型。不幸的是,在2.5亿条记录中,大约有200万条记录具有合法的文本值,其中包含" \ 0"在文中。

示例条目:

  

245150963 | DATASOURCE | 736778 | XYZNR-1B5.1 | 10-DEC-1984 00:00:00 ||| XYZNR-1B5.1 \ 1984-12-10 \ 0.5 \ 1 \ ASDF1 | pH |物理|水| XYZNR |口

如您所见,第8列的值为0。

  

XYZNR-1B5.1 \ 1984年12月10日\ 0.5 \ 1 \ ASDF1

无论我如何逃避这一点,COPY命令都会将此\ 0转换为实际的" \ x0"或者COPY命令失败,出现" ERROR:编码的无效字节序列" UTF8":0x00"。

我尝试用" sed -i"替换\ 0用:

\\0
\\\0
'\0'
\'\'0
\\\\\0

......以及其他许多我无法记住的事情,但没有一个能够奏效。

这些类型的字符串的正确转义是什么?

谢谢!

3 个答案:

答案 0 :(得分:3)

关于COPY的Per Postgres文档:

  

反斜杠字符()可以在COPY数据中用于引用数据   否则可能被视为行或列分隔符的字符。   特别是,以下字符必须以开头   反斜杠如果它们作为列值的一部分出现:反斜杠本身,   换行符,回车符和当前分隔符。

尝试将字段中该路径中的所有反斜杠字符转换为\\,而不仅仅是\ 0。

FYI \ b也是反斜杠的缩写。

所以这些都应该有效:

  

XYZNR-1B5.1 \ b1984-12-10 \ B0.5 \ B1 \ bASDF1
  XYZNR-1B5.1 \\ 1984年12月10日\\ 0.5 \\ 1 \\ ASDF1

答案 1 :(得分:1)

你需要的那个是你没有给出的一个例子:

sed -e 's/\\/\\\\/g'

您希望所有\出现,而不仅仅是\0

从文件和postgres的角度来看,我们试图将\转换为\\

sed中,\是我们需要自行转义的特殊字符,因此\变为\\\\变为\\\\因此,上面的表达。

答案 2 :(得分:0)

您确认您的sed命令实际上是在给您\\0吗?