2

ソーステーブルからdblinkを介して選択するカーソルをループしてテーブルを更新しようとすると、問題が発生します。

私は2つのデータベースDB1、DB2を持っています。

これらは2つの異なるデータベースインスタンスです。そして、私は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」をSOURCEtable@ DB2に追加するまで、すべて正常に機能します。

挿入データの値が間違っていました。

TEST_COL_Aの値は、私が予想するように、「A」である必要があります。

ただし、SOURCEテーブルに追加したNEW_COLの値が含まれています。

また、TEST_COL_Bの値には「A」が含まれています。

誰かが同じ問題に遭遇しましたか?コンパイル時にOracleがテーブルの列をキャッシュしているようです。再コンパイルせずにソーステーブルに列を追加する方法はありますか?

4

2 に答える 2

1

これによると:

Oracle Databaseは、local-procedureからremote-procedureへの依存関係以外のリモート・スキーマ・オブジェクト間の依存関係を管理しません。

たとえば、ローカルビューが、リモートテーブルを参照するクエリによって作成および定義されているとします。また、ローカルプロシージャに、同じリモートテーブルを参照する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. セット処理は、ほとんどの場合、一度に1行ずつ処理を実行します[これは、一度に1回の処理が非常に遅い]。
  2. インサートのセット処理はスケーラブルなソリューションです。アプリケーションを数万行または数百万行に拡張する必要がある場合、一度に1行ずつ拡張するソリューションはおそらく拡張されません。
  3. また、select *コンストラクトを使用することは、遭遇した理由[および他の同様の理由]のために危険です。
于 2019-12-21T01:10:53.323 に答える