我正在处理的 Oracle 实例出现一些奇怪的行为。这是 Itanium 上的 11gR1,没有 RAC,没什么特别的。最终,我在数据仓库场景中将数据从一个 Oracle 实例移动到另一个实例。
我有一个通过数据库链接运行的半复杂视图;大型表上有 4 个内连接,中型表上有 5 个左连接。
这就是问题所在:当我在 SQL Developer(或 SQL*Plus)中测试视图时,它看起来很好,没有任何重复。但是,当我实际使用视图将数据插入表中时,我得到了大量的欺骗。
编辑: - 数据将进入一个空表。查询中的所有表都在数据库链接上。唯一传入查询的是日期(例如 INSERT INTO target SELECT * FROM view WHERE view.datecol = dQueryDate) -
我尝试将 ROW_NUMBER() 函数添加到 select 语句中,由视图的 PK 分区。所有行都返回编号为 1。同样,作为插入运行的相同语句会生成与以前相同的欺骗,现在方便地编号。每个键的重复行数不同。有些记录存在 4 次,有些只存在一次。
我发现这种行为非常令人困惑。:) 它让我想起了使用 Teradata,你有 SET 表(仅限唯一行)和 MULTISET 表(允许重复行),但 Oracle 没有这样的功能。
向客户端返回行的选择应该与将这些行插入另一个位置的行为相同。我无法想象发生这种情况的正当理由,但也许我正遭受想象力的失败。;)
我想知道是否有其他人经历过这种情况,或者这是否是该平台上的错误。
解决方案
感谢@Gary,我能够通过使用“EXPLAIN PLAN FOR {my query};”来解决这个问题。和“SELECT * FROM TABLE(dbms_xplan.display);”。实际用于INSERT的说明与 SELECT 非常不同。
对于 SELECT,大多数计划操作是 'TABLE ACCESS BY INDEX ROWID' 和 'INDEX UNIQUE SCAN'。“谓词信息”块包含查询中的所有连接和过滤器。最后它说“注意 - 完全远程声明”。
对于 INSERT,没有对索引的引用。“谓词信息”块只有三行,一个新的“远程 SQL”块显示9个小 SQL 语句。
数据库已将我的查询拆分为 9 个子查询,然后尝试在本地加入它们。通过运行较小的选择,我找到了重复项的来源。
我相信这是 Oracle 编译器中围绕远程链接的错误。重写 SQL 时会产生逻辑缺陷。基本上编译器没有正确应用 WHERE 子句。我只是在测试它并给它一个包含 5 个键的 IN 列表以恢复。SELECT 带回 5 行。INSERT 将 77,000 多行放入目标中,并完全忽略 IN 列表。
{仍在寻找一种强制正确行为的方法,我可能不得不要求在远程数据库上创建视图,尽管从开发的角度来看这并不理想。当我让它工作时,我会编辑它…}