通过 dblink 选择 *
Posted
技术标签:
【中文标题】通过 dblink 选择 *【英文标题】:select * through dblink 【发布时间】:2011-05-17 13:42:14 【问题描述】:我在尝试通过 dblink 从源表中选择的循环游标来更新表时遇到了一些麻烦。
我有两个数据库 DB1、DB2。
它们是两个不同的数据库实例。 我在 DB1 中使用以下语句:
CURSOR TestCursor IS
SELECT a.*, 'A' TEST_COL_A, 'B' TEST_COL_B
FROM rpt.SOURCE@DB2 a;
BEGIN
For C1 in TestCursor loop
INSERT into RPT.TARGET
(
/*The company_name and cust_id are select from SOURCE table from DB2*/
COMPANY_NAME, CUST_ID, TEST_COL_A, TEST_COL_B
)
values
(
C1.COMPANY_NAME, C1.CUST_ID, C1.TEST_COL_A , C1.TEST_COL_B
) ;
End loop;
/*Some code...*/
End
在我将“NEW_COL”列添加到 SOURCE table@DB2 之前,一切正常
插入数据的值错误。
正如我所料, TEST_COL_A 的值应该是 'A'。
但是,它包含我在 SOURCE 表中添加的 NEW_COL 的值。
并且 TEST_COL_B 的值包含 'A'。
有人遇到过同样的问题吗? 似乎 oracle 在编译时缓存了表列。 有什么方法可以在不重新编译的情况下向源表添加列?
【问题讨论】:
您没有尝试指定严格的列列表(a.COMPANY_NAME、a.CUST_ID)而不是 a.* 吗?REMOTE_DEPENDENCY_MODE
的设置是什么?它可以是SIGNATURE
或TIMESTAMP
,每个都会导致不同的问题;-) 另外使用*
也不是一件好事,请尝试使用@heximal 提及的显式列名。
@amep: REMOTE_DEPENDENCY_MODE
仅适用于远程过程,不适用于表。
你试过在你的 SQL 中使用 NOCACHE 提示吗?好奇缓存是否是您的问题(?)
【参考方案1】:
根据this:
Oracle 数据库不管理 远程模式之间的依赖关系 以外的物体 本地程序到远程程序 依赖关系。
例如,假设本地视图 由一个查询创建和定义 引用远程表。还假设 本地过程包含 SQL 引用相同的语句 远程表。后来的定义 表已更改。
因此,本地视图和 程序永远不会失效,即使 如果视图或过程在之后使用 表被改变了,即使 视图或过程现在返回错误 使用时。在这种情况下,视图或 必须手动更改程序,以便 不返回错误。在这样的 案例,缺乏依赖管理 比不必要的更可取 依赖对象的重新编译。
在这种情况下,您并没有完全看到错误,但原因是相同的。如果您使用显式列名而不是*
,也不会有问题,无论如何这通常更安全。如果您使用的是*
,则无法避免重新编译(除非我认为*
是选择列表中的最后一项,在这种情况下,最后的任何额外列都不会导致问题 - 因为只要他们的名字没有冲突)。
【讨论】:
感谢您的帮助!这些是我们数据库中的一些现有代码,现在我认为是时候更改代码了。 :p【参考方案2】:我建议您在 DB1 中使用单个集合处理插入语句,而不是使用一次一行的时间游标 for 循环进行插入,例如:
INSERT into RPT.TARGET
select COMPANY_NAME, CUST_ID, 'A' TEST_COL_A, 'B' TEST_COL_B
FROM rpt.SOURCE@DB2
;
理由:
-
Set 处理几乎总是会超过一次执行 Row-at-a-time
处理[这真的是一次很慢的处理]。
设置处理插入是一种可扩展的解决方案。如果应用程序需要扩展到数万行或数百万行,那么一次一行的解决方案可能无法扩展。
另外,使用
select *
构造是危险的,因为你
遇到[和其他类似原因]。
【讨论】:
以上是关于通过 dblink 选择 *的主要内容,如果未能解决你的问题,请参考以下文章