Oracle:在延迟约束失败的情况下继续插入

Oracle: Continuing Inserts with failing deferred constraints

抱歉,问题很长,但我希望它完整。

我的目标是创建一个进程,用 MS-SQL 服务器创建的(和来自)数据填充 Oracle 11 数据库。 我想加载尽可能多的数据,并为未通过约束的记录创建错误报告,以便我们可以使用我们的数据测试新应用程序并改进我们的数据收集并重复此过程。

我有 NodeJS 脚本,它直接从 MS-SQL table 中读取(一次一个)并将 INSERT ... EXCEPTION/LOG ERRORS 语句发送到 Oracle 数据库。直到最后,这似乎都运作良好。有些 table 有 'deferrable constraints'(例如 parent_id 在同一个 table 中)我不能 ignore/report 所以最后我总是以提交结束延迟约束和 0 个插入行的错误:(

注意:这个问题看起来很像 Continuing Inserts in Oracle when exception is raised 但是,它没有指定延迟约束或其他工具。

问题 给定上下文(我不是真正的 Oracle 专家):

1) 是否有另一种方法来处理这些延迟约束,仍然插入有效数据并记录错误?

2) 是否有更好的工具来执行此迁移并报告当前数据问题?

嗯,听起来这些列是有充分理由可延迟的,因为在插入所有列之前,您无法知道哪些行会违反约束条件。

我不确定这是否是最佳做法,但我会做的是:在将所有记录插入 my_table 之后,在提交之前,记录并删除所有将无法通过约束的行检查,例如:

spool bad_rows.txt;
select * from my_table where parent_id not in (select id from my_table);
spool off;
delete from my_table where parent_id not in (select id from my_table);

我无法从你的问题中判断这是 one-time 数据迁移,还是常规事件。如果你打算经常这样做,你可能会考虑 creating an exception table 来捕获有问题的行,然后在加载之前禁用约束,re-enable 它们带有 EXCEPTIONS 子句(也许 SET CONSTRAINTS ALL IMMEDIATE; 来检查违反),然后在发出提交之前从 table 中删除违规行(使用它们的 rowid)。我认为你应该能够很好地自动化它。

我做这种事情的次数不够多,无法很好地回答你问题的第二部分。我可以说您的一些选择包括 (a) 使用 SQL*Loader 进行快速 direct-path 加载,它具有很好的错误处理能力,以及 (b) 创建远程数据库 link在 MS SQL Server 数据库和 Oracle 数据库之间,直接插入数据,以避免数据格式问题。希望其他人可以就良好的迁移工具提供更好的答案。