导读:本期聚焦于阿亮创作的《Oracle SQL*Loader如何跳过记录并正确处理拒绝数据?》,敬请观看详情。批量导入数据时最怕遇到坏行:字段数量不对、日期格式非法、主键冲突,任何一条都可能导致整个加载任务失败。Oracle SQL*Loader 提供了一套完整的容错机制,通过 SKIP 参数跳过文件起始的物理记录,通过 ERRORS、BADFILE 与 DISCARDFILE 控制错误记录和丢弃记录的落盘策略。SKIP 适合处理带说明头或已部分加载的文件;bad 文件保存因格式或约束错误被拒绝的记录,discard 文件保存不满足 WHEN 条件的记录。把三者配合使用,可以精确控制加载范围、错误阈值和问题数据归档路径。本文将围绕控制文件与命令行参数展开,说明跳过与拒绝记录的执行细节、参数优先级、日志阅读方法以及常见故障排查思路,并给出可直接运行的控制文件示例。

数据文件进入 SQL*Loader 后,并不会简单地区分为“成功”或“失败”,而是会按照处理阶段产生四种结果:跳过记录、成功加载记录、拒绝记录和丢弃记录。跳过发生在解析之前,SQL*Loader 直接忽略这些记录;拒绝发生在字段解析、类型转换或约束检查阶段;丢弃则发生在 WHEN 条件过滤阶段。理解这四类记录的边界,是设计可靠批量加载流程的前提。

Oracle SQL*Loader如何跳过记录并正确处理拒绝数据?

很多加载故障并不是因为 SQL*Loader 本身不稳定,而是因为开发人员没有提前规划好错误数据的去向。尤其是上游系统送来的文件,往往带有标题行、说明行、空行或部分脏数据。如果加载程序在第一条错误处就中断,会造成大量重复劳动。通过合理地组合 SKIP、ERRORS、BADFILE、DISCARDFILE 等参数,可以让 SQL*Loader 在遇到脏数据时继续加载,同时把问题记录完整保存下来,便于事后修复和重灌。

一、SKIP 参数如何跳过开头记录

SKIP 参数的作用是让 SQL*Loader 在开始加载前,先忽略数据文件开头的若干条逻辑记录。它是处理文件头最直接的方式。例如很多 CSV 文件第一行是列名,第二行才是数据。如果不跳过表头,SQL*Loader 会把列名当作数据解析,导致字段类型错误甚至整批加载失败。此时设置 SKIP=1 即可让加载从第二行开始。

SKIP 的值可以在三个位置指定:命令行参数、控制文件 OPTIONS 块、或者参数文件中。最常见的写法如下:

sqlldr userid=scott/tiger@orcl control=emp.ctl skip=1 errors=100 log=emp.log

也可以在控制文件开头使用 OPTIONS 块:

OPTIONS (SKIP=1, ERRORS=100)
LOAD DATA
INFILE 'C:\load\employees.csv'
BADFILE 'C:\load\employees.bad'
DISCARDFILE 'C:\load\employees.dsc'
APPEND
INTO TABLE employees
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
TRAILING NULLCOLS
(
  emp_id   INTEGER EXTERNAL,
  emp_name CHAR(100),
  hire_date DATE 'YYYY-MM-DD',
  salary   DECIMAL EXTERNAL
)

需要注意,SKIP 跳过的是逻辑记录,而不是字节数或文件行数。在默认情况下,一条逻辑记录对应一行文本,但如果数据文件中一条记录跨越多行,或者使用固定长度记录格式,SKIP 的计算方式就会发生变化。例如使用定长记录时,SKIP=10 表示跳过前 10 条定长记录,而不是前 10 行。另外,SKIP 只作用于数据文件的开头部分,不能让 SQL*Loader 从文件中间的任意位置开始读取。如果文件结构变化较大,建议先用文本工具确认表头行数,再设置 SKIP 值。

SKIP 还经常被用于断点续传场景。例如一次加载已经成功处理了 80 万条记录,但后续因为文件尾部损坏而中断。可以根据日志中的成功记录数,将文件中的已加载记录截掉,或者使用 SKIP 跳过这些记录后重新加载。不过要注意,如果加载过程中存在拒绝记录,日志中的“记录读取数”不会等于成功加载数加上 SKIP 数。最稳妥的方法是查看日志中的 Total logical records skippedTotal logical records readTotal logical records rejectedTotal logical records discarded 等统计项,再决定下一次 SKIP 的值。

二、拒绝记录与 bad file 的处理机制

拒绝记录是 SQL*Loader 错误处理的核心概念之一。当数据文件中的某条记录无法被正确解析或插入时,SQL*Loader 会将该条原始记录写入 bad 文件。导致拒绝的原因包括字段数量不匹配、数值字段包含非数字字符、日期格式与指定格式不一致、违反主键或非空约束、唯一索引冲突、外键约束失败等。只要控制文件中定义了字段并开始加载,任何一条引起错误的记录都会成为拒绝记录。

默认情况下,如果数据文件名为 employees.csv,bad 文件名会是 employees.bad。如果控制文件中没有显式指定 BADFILE,SQL*Loader 也可能在需要时自动创建默认的 .bad 文件。不过在实际项目中,更推荐在控制文件中明确指定 bad 文件路径,避免默认文件散落在数据文件目录中,同时便于统一管理。

ERRORS 参数控制 SQL*Loader 允许的最大拒绝记录数。传统路径加载的默认错误容忍数量通常是 50 条,超过这个数量后加载任务会停止。这个默认值在实际生产中往往偏小,尤其是历史数据迁移时,可能一个文件里就有上百条脏数据。可以将 ERRORS 设置为一个较大的值,例如 1000 或 10000,让 SQL*Loader 尽量加载所有可加载的记录。如果希望一旦出现错误就立即终止,可以设置 ERRORS=0。下面是一个允许较多错误的控制文件示例:

OPTIONS (ERRORS=2000)
LOAD DATA
INFILE 'C:\load\orders.csv'
BADFILE 'C:\load\orders.bad'
APPEND
INTO TABLE orders
FIELDS TERMINATED BY ','
TRAILING NULLCOLS
(
  order_id   INTEGER EXTERNAL,
  order_date DATE 'YYYY-MM-DD',
  customer_id INTEGER EXTERNAL,
  amount     DECIMAL EXTERNAL
)

当记录被拒绝时,SQL*Loader 会把原始数据原封不动地写入 bad 文件,同时在日志中记录拒绝原因。例如日志中会出现类似“Record 12: Rejected - Error on table ORDERS, column ORDER_DATE. ORA-01861: literal does not match format string”的信息。这条信息可以迅速定位是第几条记录、哪个字段、什么原因。修复 bad 文件中的数据后,可以直接把 bad 文件作为新的输入文件重新加载。这种方式可以避免重新处理整个原始文件,尤其适合数据量较大的场景。

需要特别注意的是,bad 文件中的记录保留的是原始文本格式,而不是经过字段拆分后的格式。因此修复时要对照控制文件的字段顺序和格式定义,不要只修改 bad 文件中的局部字符。例如日期列原值为 2023/13/01,需要改成 2023-01-01 这类控制文件可以接受的格式,而不是只把斜杠改掉后仍然保留非法月份。

三、丢弃记录与 discard file 的区别

丢弃记录和拒绝记录经常被混淆,但它们在 SQL*Loader 中是完全不同的处理结果。拒绝记录是因为无法解析或插入而失败,属于错误;丢弃记录则是记录本身可以被解析,只是因为不满足 WHEN 条件,或者没有任何 INTO TABLE 接受这条记录,因而被主动放弃。丢弃记录不写入 bad 文件,也不会计入 ERRORS 的错误数量。

只有控制文件中使用 WHEN 条件,或者同一数据文件加载到多个表并出现不满足任何表条件的情况时,才可能产生丢弃记录。例如数据文件中有 status 字段,只希望加载状态为 ACTIVE 的记录,其他状态直接丢弃。这时可以通过 WHEN 条件实现。示例控制文件如下:

LOAD DATA
INFILE 'C:\load\orders_with_status.csv'
BADFILE 'C:\load\orders_with_status.bad'
DISCARDFILE 'C:\load\orders_with_status.dsc'
DISCARDMAX 500
APPEND
INTO TABLE orders
WHEN status = 'ACTIVE'
FIELDS TERMINATED BY ','
TRAILING NULLCOLS
(
  order_id     INTEGER EXTERNAL,
  order_date   DATE 'YYYY-MM-DD',
  status       CHAR(10),
  amount       DECIMAL EXTERNAL
)

在这个示例中,状态不是 ACTIVE 的记录都能被 SQL*Loader 正常解析,但因为不满足 WHEN 条件,所以会被写入 discard 文件,而不是加载到表中。DISCARDMAX 用来限制允许丢弃的最大记录数,默认值通常是不限制。如果设置为 0,则第一条丢弃记录出现时加载会终止。如果设置了 DISCARDMAX 且达到上限,SQL*Loader 也会停止加载。因此如果需要保留所有不满足条件的记录,DISCARDMAX 可以不设置或设置一个足够大的值。

Oracle SQL*Loader跳过记录拒绝记录修改时间:2026-08-30 02:34:44

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。