SQLでデータベースリンクを介してアクセスできるリモートOracleデータベースにシノニムがあります。たとえば、
insert into my_table select * from my_synonym@my_database_link;
上記のステートメントをPLSQLブロックに入れると、コンパイルされず、エラーメッセージ「ORA-00980:シノニムの変換が無効になりました」が表示されます。標準的な説明は、シノニムが指すテーブルが削除されたなどですが、SQLでステートメントが機能するため、これは当てはまりません。
手伝ってくれた皆さん、ありがとうございました。これはOracleの制限であることが判明しました。
https://support.Oracle.com/rs?type=doc&id=453754.1
に適用されます:
PL/SQL-バージョン9.2.0.8以降このドキュメントの情報は、すべてのプラットフォームに適用されます。 2015年4月1日に関連性がチェックされました
症状
PL/SQLブロックが次のエラーで失敗する:ORA-00980:リモートデータベースからデータを選択すると、シノニム変換が無効になります。次のコードは、この問題を示しています。
DB3で(テーブルを作成)
CONNECT u3/u3 DROP TABLEタブ。 CREATE TABLE tab(c1 number);タブの値に挿入(1);コミット;
DB2の場合(DB3のテーブルの同義語を作成)
CONNECT u2/u2 DROP DATABASE LINK dblink2; 'EMT102U6'を使用してu3によって識別されるu3に接続するデータベースリンクdblink2の接続を作成します。 SELECT * FROM global_name @ dblink2; DROP SYNONYM syn2; CREATE SYNONYM syn2 FOR tab @ dblink2; SELECT * FROM syn2;
DB1で(DB2のシノニムにシノニムを作成)
CONNECT u1/u1 DROP DATABASE LINK dblink1; 'EMT102W6'を使用してu2によって識別されるu2に接続するデータベースリンクdblink1の接続を作成します。 SELECT * FROM global_name @ dblink1; DROP SYNONYM syn1; syn2 @ dblink1のSYNONYM syn1を作成します。 syn1からc1を選択します。
これはSQLでは機能しますが、PL/SQLから呼び出されると失敗します
DECLARE num NUMBER; BEGIN SELECT c1 INTO num FROM syn1;終わり; /
4行目のエラー:ORA-06550:4行目、3列目:PL/SQL:ORA-00980:同義語の変換は無効ですORA-06550:4行目、3列目:PL/SQL:SQLステートメントは無視されました
原因
この問題は、バグ2829591の9I-> 8I-> 7.3.4、GETTING ORA-980でのPL/SQLプロシージャからのクエリで報告されています。このバグは、次の理由により「NOT A BUG」としてクローズされました
PL/SQLは、コンパイルフェーズ中にデータベースリンクをたどるように中間データベース(DB2)に指示できません。したがって、このPL/SQLブロックをコンパイルして実行するには、データベースリンクdblink1とdblink2の両方をフロントエンドデータベース-DB1で定義する必要があります。実行時にデータベースリンク中に、dblink2が期待どおりにDB2で検索されます。
解決
ソリューションを実装するには、次の手順を実行してください。
- DB3を指すDB1にデータベースリンクdblink2を作成します。
SQL>データベースリンクを作成dblink2 'EMT102U6'を使用して、u3によって識別されるu3に接続します。
- DB1でPL/SQLブロックを作成してコンパイルします。
'EMT102U6'を使用してu3によって識別されるu3に接続するデータベースリンクdblink2の接続を作成します。
SELECT * FROM global_name @ dblink2; DECLARE num NUMBER;ベギン
SELECT c1 INTO num FROM syn1;終わり;/PL/SQLプロシージャが正常に完了しました。ヒント:別のオプションは、PL/SQLブロックで動的SQLを使用することです。動的SQLを使用する場合、データベースリンクはコンパイル時ではなく実行時に解決されます。
何かがSQLでは機能するがPL/SQLでは機能しない場合、ほとんどの場合、これは特権の問題です。
PL/SQLブロックに入ると、ユーザーがroleを介して受け取った特権はアクティブになりません。したがって、おそらく、基になるテーブルに対するSELECT
特権はロールを通じて付与されたため、PL/SQLブロックでは「アクティブ」ではありません。
これに対する通常の解決策は、ロールではなく、ユーザーに直接権限を付与することです。
回避策は、代わりにOracleビューを使用することです。
CREATE VIEW v_my_synomym as (select * from my_synonym@my_database_link);
次に、パッケージまたはプロシージャでビューを参照します。
insert into my_table select * from v_my_synonym;
「my_synonym」のリモートデータベース許可をチェックインすると、接続文字列で使用するユーザーのほとんどが「選択」である必要があります。この同義語が指すオブジェクトもチェックしてください(おそらく誰かがテーブルを削除した)。
テーブル/ビュー/プロシージャの所有者がSYNONYMに記載されている所有者と一致しない場合、この問題が見つかりました。
例:テーブルTABLE_BRACHの所有者がownerAで、シノニムで言及されているテーブル所有者が別の場合(ownerAではない)。
解決策:1. SYNONYMを削除します。2.正しい所有者で同じ名前で作成します。
CREATE PUBLIC SYNONYM BRANCH FOR ownerA.TABLE_BRACH ;