質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.05%

PL/SQL テーブル名が可変なSQLをオープンせずに実行(暗黙オープン)できる?

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 4,109

score 6

前提・実現したいこと

Database linkを使用して、更新先のDBを動的に制御する必要があります。
まずは送信元DBと更新先DBの差を取得し、差があれば更新先DBを更新します。

現行は1つのサーバから1つのサーバへデータ連携していたので、差分取得の際、カーソル宣言をして、暗黙カーソルオープンされてました。
改修するにあたり、1つのサーバから複数のサーバへデータ連携する必要が出てきました。
そこでDBLINKを使用するのですが、テーブルを動的にするとなると、OPENしてFETCHすることが避けられない(と思っています)ようで、現行の処理を大幅に変更する必要がありますが、それを避けたいです。


ご回答ありがとうございます。
ソースの参考を貼り付けます。
スマホからなので、抜粋ですが、宜しくお願い致します。

現行ソース(抜粋)

CREATE OR REPLACE procedure
XX.ABC(
  DB_LINK_NM varchar2(384);
) as

--差分取得カーソル変数
cursol A
  is
select a,b,c
  from TBL_A
minus
select a,b,c
  from TBL_B;

--更新処理
procedure UPDATE_MST(
  rec in A%ROWTYPE;
) as
  update TBL_A
    set A = REC.a,
        B = REC.b
  where C = REC.c
end UPDATE_MST;

begin
  --差分取得してLOOP
  for REC in A loop
    --更新処理
    UPDATE_MST(REC);
  end loop;
...

改修案(抜粋)

CREATE OR REPLACE procedure
YY.ABC(
  DB_LINK_NM varchar2(384);
) as

--変数定義
SQL varchar2(1000);
TYPE cv_type IS REF CURSOL;
cur_cv cv_type;

--差分取得SQL作成処理
procedure CERATE_GET_DIF_SQL
as
  WSSQL varchar2(1000);
begin
  WSSQL := '';
  WSSQL := WSSQL ∣∣ 'select a,b,c from TBL_A';
  WSSQL := WSSQL ∣∣ 'minus';
  WSSQL := WSSQL ∣∣ 'select a,b,c from TBL_B@';
  WSSQL := ∣∣ DB_LINK_NM ;  --◆ここで更新先テーブルのDBリンク名を結合

open cur_cv for WSSQL
  loop fetch cur_cv into REC(定義済変数とする)
    exit cur_cv%NOTFOUND;
    --〜更新処理(更新先DBをDBリンク名で指定して更新)〜
  end loop;
close cur_cv;
...
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

OPENしてFETCHすることが避けられない、って意味がよくわかりません。
現状のコードを提示できますか?
SYNONYM を使ってDB LINK先を変更することは可能です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/12/21 12:31 編集

    初心者なもなで、シノニムの有効な使い方もわからず...
    リンク先を読んでみます。
    ありがとうございます!
    また、簡単ではありますがソースを貼り付けました。
    宜しくお願い致します。

    キャンセル

  • 2016/12/21 13:20

    プロいグラム・コードは </> で引用してください。

    同じPL/SQLを同じスキーマのテーブルやDB LINK先で実行するのであれば、現行のコードをベースに
    CREATE OR REPLACE SYNONYM SYNONYM_NAME1 FOR USENAME1.TBL_B ;
    でTBL_BをSYNONYM_NAME1で PL/SQLを実行
    CREATE OR REPLACE SYNONYM SYNONYM_NAME1 FOR USENAME1.TBL_B@dblinknm ;
    でTBL_B@dblinknmをSYNONYM_NAME1でPL/SQLを実行

    キャンセル

  • 2016/12/21 14:07 編集

    ご指摘、ご回答ありがとうございます。
    同じ場合はそう実装するのですね、勉強になります。
    今回はdblink先が複数あり、その宛先がプロシージャに引数で渡ってきます。
    その場合はどうしたら良いでしょつか?

    キャンセル

  • 2016/12/22 02:20 編集

    CREATE TABLE, CREATE INDEX など、コードが実行できるだけの物もいっしょに載せてください。コードも突っ込みどころがいっぱいです。

    http://docs.oracle.com/cd/E57425_01/121/LNPLS/create_procedure.htm#i2072424
    今回はparameter_declarationでDB_LINK_NAMEを使うと、PROCEDUREの中で動的SQL
    http://docs.oracle.com/cd/E57425_01/121/LNPLS/dynamic.htm#BHCEBBAI
    が必要になるので、無意味にプログラムが複雑になってしまいます。わたしが提示したようにシンプルに CREATE OR REPLACE SYNONYM を使われては?
    parameter_declarationを使うにしても桁数は記述しません。
    コードをシンプルにする意味でcursol Aの記述方法は現行と同じで良いでしょう。
    UPDATEはPRODEDUREにするのではなく、LOOPの中に直接書いた方がシンプルです。

    SYNONYMが理解できていないようです。
    http://www.shift-the-oracle.com/words/synonym.html
    今回はプライベート・シノニムで良いでしょう。

    複数のSESSIONから今回のPRODEDUREを同時に実行するなら、UPDATE の前にSELECT ... FOR UPDATE
    http://docs.oracle.com/cd/E57425_01/121/SQLRF/statements_10002.htm#i2065646
    できちんと排他制御をする必要があります。

    今、Oracle SQLやPL/SQLの勉強中でしょうか?納期が決まっている実務に着かれているなら、職場に教えを請えるメンバーが必要です。そういうメンバーがいなければ、熟練者を増員するか、Oracle SQL入門やPL/SQL基礎などの有償研修に行かないと難しいでしょう。
    http://www.oracle.com/jp/education/promotion/course-flow-database.html

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.05%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る