Oracle

オブジェクトを修正したらシノニムも更新が必要?【Oracle SQL】

記事内に商品プロモーションを含む場合があります

こんにちは、すみです。

当記事は、こんな内容になっております。

  • Oracleでテーブルやプロシージャなどのオブジェクトを修正したけど、シノニムも更新しないといけないの?
  • そもそもシノニムってなに?

オブジェクトの中身を修正しただけの場合は、シノニムは更新しなくて大丈夫【結論】

たとえば、こんなプロシージャがあったとします。

  • 名称:Aプロシージャ
  • シノニム:a
  • 処理:実行すると「テスト」という文字列を返す

仕様変更により、Aプロシージャを実行した際に返す文字列を「てすと」に変更することにしました。

Aプロシージャを修正して再コンパイルします。これにより、Aプロシージャを実行すると「てすと」とひらがなで返すようになりました。

ところが、aシノニムは再作成していませんが、どのような挙動になるのでしょうか。

結論としては、aを実行した際にも、きちんと「てすと」と返ってくるようになります。

そもそもOracleの「シノニム」ってなに?

一言で表すなら、シノニムとはオブジェクトにあだ名をつけることです。

まず、オブジェクトとは

  • テーブル
  • ビュー
  • インデックス
  • プロシージャ
  • ユーザー

などを指します。

先ほどの例でいうならば、Aという名前のプロシージャに、aという別名をつけることができます。この別名をつける機能のこと、また別名そのもののことを指します。

プロシージャ名であるAを指定して実行しても、シノニムであるaを指定して実行しても、実行結果は変わりません。

なぜかというと、シノニムaはプロシージャAのコピーではなく、あくまでもプロシージャAを参照しているにすぎないからです。

シノニムであるaを指定して実行しても、結果的に実行されているのはAプロシージャそのものです。先ほどの話にも繋がりますが、Aプロシージャ自体の名前や場所が変わらない限り、aシノニムを再作成する必要はありません。

シノニムを定義するメリットは、主にセキュリティと利便性にあるようです。

シノニムでセキュリティが向上する

シノニムで別名を付与することで、ユーザーはオブジェクトの実態を知らなくても、シノニムを経由してオブジェクトにアクセスすることができるようになります。

また、オブジェクト自体にアクセス権限を付与せずに、シノニムにのみ権限を付与することでセキュリティリスクを抑えつつ、利便性も損なわないように設定できます。

少しわかりにくいですが…。

たとえば、TESTスキーマに存在するAテーブルがあったとします。DB管理者であるBさんは、開発者すみに対して、TESTスキーマやAテーブルに直接アクセスしてほしくありません。でも、すみは業務上Aテーブルを参照する必要はあります。

そこで、SUMIスキーマにAテーブルのシノニムaを作成し、すみにアクセス権限を与えました。これにより、すみはTESTスキーマやAテーブルを直接操作することはできませんが、aシノニムを利用してAテーブルのデータを見ることができるようになりました。

みたいな感じでしょうか。

シノニムで利便性が向上する

先ほども少し触れましたが、別スキーマにあるオブジェクトのシノニムが自分のスキーマにあれば、実行時にいちいちスキーマ名を指定する手間が省けます。少し便利ですね。

また、状況によって別のオブジェクトに対して同じシノニムを定義する場合もあるようです。これはchatGPT先生に教えてもらったので、業務で実際にやっていることではないのですが、たとえば開発環境と本番環境で異なるオブジェクトを参照するようなケース。

開発環境ではAテーブル、本番環境ではBテーブルを同じような役割で参照している場合、どちらも同じ「ab」というシノニム名をつけておけば、開発・本番で同じように実行することができて便利とのこと。確かに便利そう。

今回の疑問に至った経緯

私のいる現場では、SQLファイルにプロシージャとシノニムの定義が一緒に記載されており、修正時にはそのSQLファイルを実行することでコンパイルしていました。

あるときプロシージャを修正することになったのですが、SQLファイルを見ると、シノニムの定義は「CREATE」のみでした。

ほかのSQLファイルは「CREATE OR REPLACE」となっているので、そのままSQLファイルを実行すればシノニムも再作成されるはず。しかし今回のSQLファイルはすでにシノニムが作成されているので、そのままだとエラーになります。

これまでも何度も修正されてきたプロシージャだったので、おそらくこれまではシノニムの再作成に失敗しているはず…。これって大丈夫なのだろうか?と疑問に思いました。

プロシージャ自体は修正後コンパイルされているので、直接実行する分には問題ないはずです。しかしシノニムを実行したときに、初回作成時の古い状態で実行されたりしないのだろうか?

すでに結論として記載した通り、シノニムを再作成しなくてもプロシージャの名前や場所が変わらない限り、シノニムを再作成しなくても問題ありません。

ところがこのとき、chatGPT先生に聞いたところ、「シノニムを再作成しないと古いプロシージャが参照される」との答えが!

私の聞き方が良くなかったのだと思いますが(このときのプロンプトがすでになく、ブログに書けない…無念)、これで私は混乱してしまいました…。

Live SQLで挙動を試してみました

聞いても調べてもよくわからないので、実際に動かして確認することにしました。調べてみると、Live SQLという、ブラウザさえあれば簡易的にOracle SQLを実行できるツールがあることがわかり、試してみることに。(Oracleの公式ツールです)

こんなSQLを書いてみました。

— プロシージャを作成
create or replace procedure PROCEDURE_1
is
begin
DBMS_OUTPUT.PUT_LINE(‘テスト’);
end PROCEDURE_1;
/
— プロシージャを実行
exec PROCEDURE_1;

— シノニムを作成
create or replace synonym prc1 for PROCEDURE_1;

— シノニムを確認
select * from all_synonyms where table_name = ‘PROCEDURE_1’;

— シノニムを実行
exec prc1;

こんな順番で実行してみます。

  1. 「テスト」と表示するプロシージャを作成
  2. プロシージャを実行→「テスト」と表示されるはず
  3. シノニムを作成、シノニムが作成されていることを確認
  4. シノニムを実行→「テスト」と表示されるはず
  5. プロシージャを修正し、「てすと」と表示されるようにする
  6. プロシージャを実行→「てすと」と表示されるはず
  7. シノニムを実行→「てすと」と表示されるはず

プロシージャが作成されました。

プロシージャを実行しました。「テスト」と表示されています。

シノニムが作成されました。

念のため確認してみました。無事にシノニムが作成されています。

シノニムを実行しました。「テスト」と表示されています。

さて、次は、プロシージャの内容を書き換えます。「テスト」ではなく「てすと」と表示されるようにしましょう。

プロシージャを実行してみます。

「てすと」と表示されるようになりました。

それでは、シノニムを再作成することなく、このままシノニムを実行してみます。

無事に「てすと」と表示されました!

改めてchatGPT先生に聞いてみました

実行結果を踏まえて、もう一度chatGPT先生に聞いてみました。ちゃんと聞けば正しい答えを教えてくれるはず…!

私のプロンプトはこちらです。

あなたは凄腕のデータベースエンジニアです。
特にOracle社のDBに詳しい存在です。
Oracleのシノニムについて教えてください。

シノニムとは、テーブルやプロシージャなどのオブジェクトにつける別名という認識です。
もし、テーブルやプロシージャなどのオブジェクトに更新が入った場合に、
シノニムを更新しなかった場合はどういう挙動になるのでしょうか?


①戻り値として「1」を返す「プロシージャ1」を作成
②「プロシージャ1」のシノニム「プロ1」を定義
③プロ1を実行すると、戻り値1が返る
④「プロシージャ1」について、戻り値を「1」ではなく「2」で返すように修正する
⑤プロ1を実行する

このとき、⑤ではどんな値が返りますか?

これに対して、いろいろと実例コードなどを教えてくれましたが、結論としてはこちら。

シノニム「プロ1」は、「プロシージャ1」のエイリアスとして動作しています。そのため、「プロシージャ1」を変更した場合でも、シノニム「プロ1」は最新の「プロシージャ1」を参照します。

したがって、⑤の時点で「プロ1」を実行すると、最新の「プロシージャ1」の挙動に従い、戻り値「2」が返されます。

引用:chatGPT

正しい答えを返してくれるようになりました。

シノニムはなんのために「再作成」するの?【新たな疑問】

シノニムはあくまでもオブジェクトの住所を辿っているだけにすぎません。そのため、オブジェクトの中身が変わったとしても、オブジェクトの住所(格納場所)が変わらない限りは、シノニムを再作成する必要はないと言えます。

逆に言うと、オブジェクトの格納場所が変わった場合は、シノニムがオブジェクトを辿ることができなくなってしまいますので、再作成をする必要があります。

また、オブジェクトを削除して再作成した場合でも、シノニムを再作成する必要しなければなりません。削除された元のオブジェクトと、再作成されたオブジェクトは参照先が異なるため、シノニムを再作成しなければ参照できなくなってしまうためです。

ちなみに念のため、こんなケースについてchatGPT先生に聞いてみました。

たとえば、Aプロシージャがあり、そこでBテーブルをSELECTする処理があったとします。
このとき、Bテーブルのスキーマが変更された場合についても、Aプロシージャ自体のスキーマが変更されていなければ、Aプロシージャのシノニムを再作成する必要はないという理解で良いでしょうか?

この質問に対して、chatGPT先生の回答がこちら。

Aプロシージャのシノニム自体は再作成の必要はありません。(中略)
シノニムは単なるエイリアス(別名)であり、元のオブジェクト(この場合はAプロシージャ)へのリンクを提供します。
シノニム自体はオブジェクトの状態(有効/無効)やコンパイル状態には影響を与えません。(中略)

ご質問では、Aプロシージャの参照先であるBテーブルのスキーマが変更され、その結果Aプロシージャを再コンパイルする必要がある、という状況です。この場合:

  • Aプロシージャのシノニムは、Aプロシージャが無効化されたとしてもリンクを保持します。再コンパイルが完了すれば、シノニム経由で問題なくAプロシージャを実行できます。
  • よって、この場合はシノニムの再作成は不要です。

引用:chatGPT

プロシージャ自体の格納場所は変わらないけど、プロシージャの中で参照しているテーブルの参照先が変わるケース。この場合、プロシージャ自体は再コンパイルする必要がありますが、シノニムの再作成は不要とのこと。

やはりあくまでも、「実態(この場合はプロシージャ)がどこに存在しているか?」が重要で、プロシージャが参照しているオブジェクトの参照が変わっても、プロシージャのシノニムを再作成する必要はないようです。

ちなみにこの例であれば、Bテーブルにシノニムが作成されていた場合、再作成が必要になりますね。

まとめ

シノニムに対して「オブジェクトの別名」という程度の知識はあったのですが、今回調べてみて、より理解が深まりました。

シノニムの実行=オブジェクトの住所を辿って、オブジェクトを実行させる

シノニムが持っているのは、あくまでもオブジェクトの住所です。そのため、オブジェクトの中身がどんなに変わっても、住所(参照)が変わらない限りは再作成をせずとも、常に最新ののオブジェクトが実行されます。

ただし、

  • オブジェクトの格納先を変更
  • オブジェクトを削除して再作成

などした場合、オブジェクトの住所が変わってしまいますので、シノニムはオブジェクトを辿れなくなってしまいます。この場合は、オブジェクトの住所変更に合わせてシノニムも再作成する必要があります。

この記事がどなたかのお役に立てれば幸いです。ありがとうございました!