通过 dblink 选择 *

发布于 2024-11-08 07:17:29 字数 857 浏览 5 评论 0原文

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

I have some trouble when trying to update a table by looping cursor which select from source table through dblink.

I have two database DB1, DB2.

They are two different database instance.
And I am using this following statement in 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

Everything works fine until I add a column "NEW_COL" to SOURCE table@DB2

The insert data got the wrong value.

The value of TEST_COL_A , as I expect, should be 'A'.

However, it contains the value of NEW_COL which i add at SOURCE table.

And the value of TEST_COL_B contains 'A'.

Have anyone encounter the same issue?
It seems like oracle cache the table columns when it compile.
Is there any way to add a column to source table without recompile?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

简单 2024-11-15 07:17:29

根据

Oracle数据库不管理
远程模式之间的依赖关系

本地过程到远程过程
依赖关系。

例如,假设本地视图
由查询创建和定义
引用远程表。还假设
本地过程包含 SQL
引用相同内容的声明
远程表。后来,定义
该表已更改。

因此,本地视图和
程序永远不会失效,甚至
如果视图或过程在之后使用
该表已更改,即使
视图或过程现在返回错误
使用时。在这种情况下,视图或
必须手动更改程序,以便
不会返回错误。在这样的
案例,缺乏依赖管理
比不必要的更可取
重新编译依赖对象。

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

According to this:

Oracle Database does not manage
dependencies among remote schema
objects other than
local-procedure-to-remote-procedure
dependencies.

For example, assume that a local view
is created and defined by a query that
references a remote table. Also assume
that a local procedure includes a SQL
statement that references the same
remote table. Later, the definition of
the table is altered.

Therefore, the local view and
procedure are never invalidated, even
if the view or procedure is used after
the table is altered, and even if the
view or procedure now returns errors
when used. In this case, the view or
procedure must be altered manually so
that errors are not returned. In such
cases, lack of dependency management
is preferable to unnecessary
recompilations of dependent objects.

In this case you aren't quite seeing errors, but the cause is the same. You also wouldn't have a problem if you used explicit column names instead of *, which is usually safer anyway. If you're using * you can't avoid recompiling (unless, I suppose, the * is the last item in the select list, in which case any extra columns on the end wouldn't cause a problem - as long as their names didn't clash).

万劫不复 2024-11-15 07:17:29

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

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

基本原理:

  1. 集合处理几乎将总是优于一次一行
    处理[这是一次非常慢的处理]。
  2. 设置处理插入是一个可扩展的解决方案。如果应用程序需要扩展到数万行或数百万行,则一次行解决方案将无法扩展。
  3. 此外,使用 select * 构造是危险的,因为您
    遇到[和其他类似原因]。

I recommend that you use a single set processing insert statement in DB1 rather than a row at a time cursor for loop for the insert, for example:

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

Rationale:

  1. Set processing will almost always out perform Row-at-a-time
    processing [which is really slow-at-a-time processing].
  2. Set processing the insert is a scalable solution. If the application will need to scale to tens of thousands of rows or millions of rows, the row-at-a-time solution will not likely scale.
  3. Also, using the select * construct is dangerous for the reason you
    encountered [and other similar reasons].
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文