SQLLDR 在接受具有相同值的其他记录时拒绝某些记录

SQLLDR rejecting some records while accepting others which have the same value

我使用相同的控制文件将 TSV 文件加载到我们的数据库已有一段时间了,直到最近才出现问题。

控制文件看起来有点像这样(省略了实际的 table 和列名):

INTO TABLE "TABLE_NAME" WHEN RECORD_TYPE = 'TYPE'
FIELDS TERMINATED BY X'9'
TRAILING NULLCOLS
    (ID CONSTANT 'FILE_ID',
     FILE_NAME "'FILE_NAME'",
     IMPORT_START "SYSDATE",
     RECORD_TYPE POSITION(1),
     COLUMN_X,
     COLUMN_Y,
     COLUMN_Z,
    )

其中 RECORD_TYPE 是记录中的第一个值。即

TYPE *TAB* COLUMN_X *TAB* COLUMN_Y *TAB* COLUMN_Z

当我尝试加载一个文件时,它加载时没有任何错误,但是在加载大多数记录类型时丢弃了 一些 特定记录类型,在日志文件中给我以下消息:

Record x: Discarded - failed all WHEN clauses.

我已经查看了文件,看不出数据有什么问题。

我尝试更改各个 INTO TABLE "TABLE_NAME" WHEN RECORD_TYPE 块的顺序,以便失败的块更靠近顶部,绝望地尝试看看它是否会有所作为,并且由于某种原因它起作用了。

这对我来说没有任何意义,因为我没有更改任何 WHEN 子句的条件,只更改了它们的顺序,所以我不应该失败 all 在任何一种情况下......我想知道是否有更好的 SQLLDR 经验的人能够阐明这种奇怪的行为?

Multiple INTO TABLE 子句的工作方式非常不直观。参见 this Ask Tom post. What I think is happening is that the first INTO TABLE clause processes the line successfully, ending at the end of the line, and then the second INTO TABLE clause starts in the same place, doesn't find any characters at all because it's at the end of the line, so it fails the WHEN clause. See also this documentation

听起来您需要在每个 INTO TABLE 子句的第一列使用 POSITION(1) 参数来告诉它从行的开头开始:

INTO TABLE "TABLE_NAME" WHEN RECORD_TYPE = 'TYPE'
FIELDS TERMINATED BY X'9'
TRAILING NULLCOLS
    (ID POSITION(1) "'FILE_ID'",
     FILE_NAME "'FILE_NAME'",
     IMPORT_START "SYSDATE",
     RECORD_TYPE POSITION(1),
     COLUMN_X,
     COLUMN_Y,
     COLUMN_Z,
    )