2

尝试通过循环从源表中选择通过 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 在编译时缓存了表列。有没有办法在不重新编译的情况下向源表添加列?

4

2 回答 2

1

据此:_

除了本地过程到远程过程的依赖关系之外,Oracle 数据库不管理远程模式对象之间的依赖关系。

例如,假设本地视图是由引用远程表的查询创建和定义的。还假设一个本地过程包括一个引用同一个远程表的 SQL 语句。稍后,表的定义被更改。

因此,本地视图和过程永远不会失效,即使视图或过程在表更改后使用,即使视图或过程现在在使用时返回错误。在这种情况下,必须手动更改视图或过程,以免返回错误。在这种情况下,缺少依赖管理优于不必要地重新编译依赖对象。

在这种情况下,您并没有完全看到错误,但原因是相同的。如果您使用显式列名而不是 ,您也不会遇到问题*,这通常更安全。如果您正在使用*,则无法避免重新编译(除非我认为这*是选择列表中的最后一项,在这种情况下,末尾的任何额外列都不会引起问题-只要它们的名称没有t 冲突)。

于 2011-05-17T14:31:43.847 回答
0

我建议您在 DB1 中使用单个集合处理插入语句,而不是在一次游标中使用一行进行插入,例如:

INSERT into  RPT.TARGET 
select COMPANY_NAME, CUST_ID, 'A' TEST_COL_A, 'B' TEST_COL_B
FROM rpt.SOURCE@DB2
;

理由:

  1. 集合处理几乎总是会执行一次 Row-at-a-time 处理 [这确实是一次慢速处理]。
  2. 设置处理插入是一种可扩展的解决方案。如果应用程序需要扩展到数万行或数百万行,那么一次一行的解决方案将不可能扩展。
  3. 此外,select *由于您遇到的原因[和其他类似原因],使用该构造是危险的。
于 2019-12-21T01:10:53.323 回答