使用sqlldr加载TPC-DI数据至DimTime表遇ORA-12899错误求助
问题分析与解决
行尾字符判断
报错显示最后一列实际长度为6,而字段定义是CHAR(5),结合TPC-DI可能跨系统生成数据的情况,行尾大概率是Windows风格的CRLF换行符(即ASCII的0x0D+0x0A,也就是回车+换行)。Oracle Linux默认使用LF(0x0A)作为换行符,当SQL*Loader读取Windows格式的文件时,会把行首的回车符(0x0D)当成最后一列数据的一部分,导致"false"/"true"(5个字符)加上回车符(1个字符)总长度为6,触发字段长度超限错误。
你可以用以下命令验证:
- 查看文件换行符:
file path/to/Time.txt,如果输出包含"with CRLF line terminators"则确认是Windows格式。 - 显示不可见字符:
cat -v path/to/Time.txt,每行末尾出现^M就是回车符的标识。
解决方法
方法1:转换文件格式为Linux风格
直接将Windows格式的文件转换为Linux格式,用dos2unix工具:
# 安装工具(如果未安装) dnf install dos2unix -y # 转换文件 dos2unix path/to/Time.txt
转换后重新执行SQL*Loader加载即可。
方法2:修改SQL*Loader控制文件,指定正确的记录终止符
在ctl文件中明确指定记录终止符为CRLF,替换原INFILE行:
LOAD DATA INFILE 'path/to/Time.txt' "STR X'0D0A'" TRUNCATE INTO TABLE DimTime FIELDS TERMINATED BY '|' OPTIONALLY ENCLOSED BY '"' TRAILING NULLCOLS ( SK_TimeID, TimeValue DATE "HH24:MI:SS", HourID, HourDesc, MinuteID, MinuteDesc, SecondID, SecondDesc, MarketHoursFlag, OfficeHoursFlag )
注:控制文件中直接使用双引号即可,无需转义"。
方法3:在字段处理时移除回车符
如果不想修改文件或INFILE配置,可以在字段映射中通过函数去掉回车符:
LOAD DATA INFILE TRUNCATE INTO TABLE DimTime FIELDS TERMINATED BY '|' OPTIONALLY ENCLOSED BY '"' TRAILING NULLCOLS ( SK_TimeID, TimeValue DATE "HH24:MI:SS", HourID, HourDesc, MinuteID, MinuteDesc, SecondID, SecondDesc, MarketHoursFlag, OfficeHoursFlag "REPLACE(:OfficeHoursFlag, CHR(13), '')" )
CHR(13)对应回车符,该函数会将字段中的回车符替换为空,确保长度符合要求。
为什么之前的尝试无效
- 你设置的
STR X'0A'是Linux的LF换行符,但文件实际是CRLF,SQL*Loader会把CR(0x0D)当成最后一列的内容,LF才作为记录终止符,所以无效。 TRIM()函数默认只处理空格类字符,不会移除回车这类控制字符,因此无法解决问题。
内容的提问来源于stack exchange,提问作者Sayyor Y
相关产品推荐
相关产品推荐

