我有一个3200万元组的数据集,我使用COPY FROM将这些元组复制到表中。在前700万个元组中,有3个格式不正确的元组。在这些情况下,下一条记录不是在当前记录下面,而是附加到同一行上当前记录的末尾。所以不是

record1
record2

是的
record1record2

我通过导航到换行符应该在的位置并在每个实例中按一次“Enter”来解决这个问题,这是一个典型的换行条目。一旦我修复了这些行,COPY函数就可以很好地读取它们了。对我来说,这意味着“Enter”是插入换行符的有效方法,因为COPY函数可以读取“Enter”生成的换行符,没有问题。
然而,后来当我通过第700万元组时,我遇到了:
ERROR: literal newline found in data
HINT: Use "\n" to represent newline.
Context: COPY time_raw, line 7308000

SQL状态:22P04
我查看了那条记录的数据,发现它与上面或下面的记录没有什么不同。为了确定,我在记录7308000的开头按了“Backspace”,将其上移一行到记录7307999的结尾,就像上面的格式record1record2一样。然后我按了“回车”键,以确保开始记录7308000的换行符与之前复制的字符完全相同。同样,结束记录7307999的换行符与我用来分隔先前格式错误的记录的换行符完全相同(再次,COPY毫无问题地引入了这个换行符)。为了弥补我的不足,我对记录7308001也做了同样的操作,确保结束记录7308000的换行符与我之前键入的换行符相同,该换行符被接受。但是,在保存并再次尝试从文件复制时,我得到:
ERROR: literal newline found in data
HINT: Use "\n" to represent newline.
Context: COPY time_raw, line 7307999

很明显,这个错误已经升级了,先前复制的换行符突然变得无效。我再次查看数据,将7307999的开头移到7307998的结尾,然后按“回车”键插入一个换行符,该换行符副本已识别为对700多万条记录有效。所以在这一点上,我相信7307998的结尾是一个新行字符,应该已经被证明可以在前面的COPY中工作。我再次运行查询,现在得到:
ERROR: literal newline found in data
HINT: Use "\n" to represent newline.
Context: COPY time_raw, line 7307998

错误再次上移。据我所知,我只是输入了与之前相同的“输入”换行符,由于某种原因,超过7308000个副本会将其视为无效。
这些是数据集的第7307996-7308000行(56列,最无意义)
2012-02-23T13:10:03.1769237+00:00   9863996 12604   13807   8171    0000    0001    0000    0000    0000    0000    0000    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   1   1   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
2012-02-23T13:10:03.1869189+00:00   9863997 12604   13807   8171    0000    0001    0000    0000    0000    0000    0000    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   1   1   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
2012-02-23T13:10:03.1969230+00:00   9863998 12604   13807   8171    0000    0001    0000    0000    0000    0000    0000    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   1   1   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
2012-02-23T13:10:03.2069124+00:00   9863999 12604   13807   8171    0000    0001    0000    0000    0000    0000    0000    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   1   1   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
2012-02-23T13:10:03.2169261+00:00   9864000 12604   13807   8171    0000    0001    0000    0000    0000    0000    0000    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   1   1   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

我在stackoverflow编辑器中在每条记录之后添加了一个“Enter”,以便一个接一个地显示它们,但关键是相关的中间线(7307998)的格式与其他记录完全相同,并且我确保它被COPY函数已经显示为有效字符的新行包围。每次我试图确保记录周围的换行符与之前使用的换行符相同时,错误都会上升一行。我不知道在这种情况下该怎么办。
我的问题是:
copy time_raw from E'C:\\Users\\bozon92\\Documents\\YorkU\\Summer 2016\\4080 Project\\Other Files\\allData.txt';

我试过附加“with(format csv,delimiter'\t')”但这告诉我复制分隔符必须是一个单字节字符,而“with(format csv,delimiter'')”(“”是一个文本制表符空间,而不是\t)它给出了相同的错误性质,只是语法略有不同:
ERROR:  unquoted newline found in data
HINT:  Use quoted CSV field to represent newline.
CONTEXT:  COPY time_raw, line 7307998

只是“没有引用”而不是“字面”。
有人告诉我,我可以将数据削减到700万个元组,我最终可能会这样做,但我想知道为什么会发生这个问题,这样我以后就可以避免了。我不知道这些数据有什么问题,因为这些特定的记录看起来很好,而且前后的格式完全相同,所以我如何处理这个字面上的换行问题?我不知道该如何处理,因为我甚至找不到任何问题的痕迹。

最佳答案

根据PostgreSQL源代码片段,copy.c

 /* Process \n */
 if (c == '\n' && (!cstate->csv_mode || !in_quote))
 {
     if (cstate->eol_type == EOL_CR || cstate->eol_type == EOL_CRNL)
         ereport(ERROR,
             (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
             !cstate->csv_mode ?
             errmsg("literal newline found in data") :
             errmsg("unquoted newline found in data"),
             !cstate->csv_mode ?
             errhint("Use \"\\n\" to represent newline.") :
             errhint("Use quoted CSV field to represent newline.")));
      cstate->eol_type = EOL_NL;      /* in case not set yet */
      /* If reach here, we have found the line terminator */
      break;
}

这意味着您的输入数据在字符串的某个地方使用byte0x0A,例如,您使用"abcNxyz",而不是N,实际上存在值为0x0A的字节。
解决方案是改用string"abc\n"
您应该能够找到所有虚假的换行符,并使用一些脚本(可能是Python或Perl)将它们替换为\n

关于postgresql - 解决Postgres中的“错误:在数据中找到文字换行符”?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38315121/

10-14 00:48