J'ai un synonyme sur une base de données Oracle distante à laquelle je peux accéder en SQL via un lien de base de données, par exemple,
insert into my_table select * from my_synonym@my_database_link;
Si je mets l'instruction ci-dessus dans un bloc PLSQL, elle ne sera pas compilée, donnant le message d'erreur "ORA-00980: la traduction des synonymes n'est plus valide". L'explication standard est la table vers laquelle le synonyme pointe a été supprimée, etc., mais ce n'est pas le cas car l'instruction fonctionne en SQL.
Merci à tous ceux qui ont essayé d'aider. Cela s'est avéré être une limitation Oracle:
https://support.Oracle.com/rs?type=doc&id=453754.1
S'APPLIQUE À:
PL/SQL - Version 9.2.0.8 et versions ultérieures Les informations contenues dans ce document s'appliquent à toutes les plateformes. Vérification de la pertinence le 01-avr-2015
SYMPTÔMES
Un bloc PL/SQL échoue avec l'erreur: ORA-00980: la traduction des synonymes n'est plus valide lors de la sélection de données dans une base de données distante. Le code suivant illustre ce problème:
Sur DB3 (créer la table)
CONNECT u3/u3 DROP TABLE tab; Onglet CREATE TABLE (numéro c1); INSÉRER DANS L'onglet VALEURS (1); COMMETTRE;
Sur DB2 (créez un synonyme de la table sur DB3)
CONNECT u2/u2 DROP DATABASE LINK dblink2; CRÉER UN LIEN DE BASE DE DONNÉES dblink2 CONNECTER À u3 IDENTIFIÉ PAR u3 À L'AIDE DE 'EMT102U6'; SELECT * FROM nom_globale @ dblink2; DROP SYNONYM syn2; CRÉER SYNONYM syn2 POUR tab @ dblink2; SELECT * FROM syn2;
Sur DB1 (créez un synonyme du synonyme sur DB2)
CONNECT u1/u1 DROP DATABASE LINK dblink1; CRÉER UN LIEN DE BASE DE DONNÉES dblink1 SE CONNECTER À u2 IDENTIFIÉ PAR u2 À L'AIDE DE 'EMT102W6'; SELECT * FROM nom_globale @ dblink1; DROP SYNONYM syn1; CRÉER SYNONYME syn1 POUR syn2 @ dblink1; SELECT c1 from syn1;
Cela fonctionne en SQL mais échoue lorsqu'il est appelé depuis PL/SQL
DECLARE num NUMBER; COMMENCER SELECT c1 EN num DE syn1; FIN; /
ERREUR à la ligne 4: ORA-06550: ligne 4, colonne 3: PL/SQL: ORA-00980: la traduction des synonymes n'est plus valide ORA-06550: ligne 4, colonne 3: PL/SQL: instruction SQL ignorée
CAUSE
Ce problème a été signalé dans le bogue 2829591 QUERING OF A PL/SQL PROCEDURE IN 9I -> 8I-> 7.3.4, GETTING ORA-980. Ce bogue a été fermé comme "PAS UN BUG" pour les raisons suivantes
PL/SQL ne peut pas demander à la base de données intermédiaire (DB2) de suivre le lien de la base de données pendant la phase de compilation. Par conséquent, pour que ce bloc PL/SQL se compile et s'exécute, les deux liens de base de données dblink1 et dblink2 doivent être définis sur la base de données frontale - DB1. Pendant l'exécution, le lien de la base de données dblink2 sera recherché dans DB2 comme prévu.
SOLUTION
Pour implémenter la solution, veuillez exécuter les étapes suivantes:
- Créer un lien de base de données dblink2 sur DB1 pointant vers DB3
SQL> créer un lien de base de données dblink2 se connecter à u3 identifié par u3 en utilisant 'EMT102U6';
- Créez et compilez le bloc PL/SQL sur DB1.
CRÉER UN LIEN DE BASE DE DONNÉES dblink2 CONNECTER À u3 IDENTIFIÉ PAR u3 À L'AIDE DE 'EMT102U6';
SELECT * FROM nom_globale @ dblink2; DECLARE num NUMBER; COMMENCER
SELECT c1 INTO num FROM syn1; FIN;/PL/SQL procédure terminée avec succès.CONSEIL: Une autre option consiste à utiliser SQL dyanmique dans le bloc PL/SQL comme solution de contournement. Lors de l'utilisation de SQL dynamique, le lien de base de données n'est pas résolu au moment de la compilation mais au moment de l'exécution.
Si quelque chose fonctionne en SQL mais pas en PL/SQL, alors dans la plupart des cas, c'est un problème de privilèges.
Tout privilège qu'un utilisateur a reçu via un rôle n'est pas actif lorsque vous entrez un bloc PL/SQL. Donc, très probablement, le privilège SELECT
sur la table sous-jacente a été accordé via un rôle et n'est donc pas "actif" dans le bloc PL/SQL.
Le remède habituel consiste à accorder les privilèges directement à l'utilisateur, et non via un rôle.
La solution de contournement consiste à utiliser une vue Oracle à la place.
CREATE VIEW v_my_synomym as (select * from my_synonym@my_database_link);
Référencez ensuite la vue dans votre package ou procédure, c'est-à-dire:
insert into my_table select * from v_my_synonym;
L'archivage dans les bases de données distantes pour "mon_synonyme" doit être presque "sélectionner" pour l'utilisateur que vous utilisez dans la chaîne de connexion, vérifiez également l'objet vers lequel ce synonyme pointe (peut-être que quelqu'un a supprimé la table).
J'ai trouvé ce problème lorsque le propriétaire de la table/vue/procédure ne correspond pas au propriétaire mentionné dans SYNONYM.
Exemple: si le propriétaire de la table TABLE_BRACH est propriétaireA et dans le synonyme le propriétaire de table mentionné est autre chose (pas propriétaireA).
Solution: 1. Déposez le SYNONYM 2. Créez-le avec le même nom avec le bon propriétaire.
CREATE PUBLIC SYNONYM BRANCH FOR ownerA.TABLE_BRACH ;