ORA-00980错误:PLSQL中同义词转换无效

14

我在一个远程的Oracle数据库上有一个同义词,我可以通过数据库链接在SQL中访问它,例如:

insert into my_table select * from my_synonym@my_database_link;

如果我将上述语句放入PLSQL块中,它不会编译,并出现错误消息“ORA-00980:同义词翻译不再有效”。标准解释是同义词指向的表已被删除等,但这并不是问题的原因,因为该语句在SQL中可以工作。


Ask Tom在这个主题上有一个条目,其中包含类似于您的情况的场景,链接为https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:7095288486502。 - Patrick Bacon
以下是对下面答案(来自Burleson Consulting)的很好的补充:http://www.dba-oracle.com/sf_ora_00980_synonym_translation_is_no_longer_valid.htm - Benj
5个回答

3

如果在SQL中可以正常工作但在PL/SQL中无法正常工作,则大多数情况下这是一个权限问题。

任何用户通过角色获得的权限在进入PL/SQL块时都不会生效。因此,底层表上的SELECT权限很可能是通过角色授予的,因此在PL/SQL块中不是“活动的”。

通常的解决方法是直接将权限授予给用户,而不是通过角色授予。


谢谢您回答我的问题,但在这种特殊情况下没有涉及到授权:my_synonym是通过数据库链接my_database_link访问的。 - D Veloper
1
@DVeloper:...并且存储在DBLink中的用户需要授予权限才能访问底层表。 - user330315

3
感谢所有试图提供帮助的人。这实际上是 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 tab; CREATE TABLE tab(c1 number); INSERT INTO tab VALUES (1); COMMIT;
在DB2上(为DB3上的表创建同义词) CONNECT u2/u2 DROP DATABASE LINK dblink2; CREATE DATABASE LINK dblink2 CONNECT TO u3 IDENTIFIED BY u3 USING 'EMT102U6'; 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; CREATE DATABASE LINK dblink1 CONNECT TO u2 IDENTIFIED BY u2 USING 'EMT102W6'; SELECT * FROM global_name@dblink1; DROP SYNONYM syn1; CREATE SYNONYM syn1 FOR syn2@dblink1; SELECT c1 from syn1;
这在SQL中可以工作,但从PL/SQL调用时失败
DECLARE num NUMBER; BEGIN SELECT c1 INTO num FROM syn1; END; /
第4行出错: ORA-06550: 行4,列3: PL/SQL:ORA-00980:同义词翻译无效 ORA-06550: 行4,列3: PL/SQL:SQL语句被忽略
原因:
此问题报告在Bug 2829591中。在9I->8I->7.3.4中从PL/SQL过程查询时,会出现ORA-980。对于以下原因,此错误已关闭为“不是错误”:
PL/SQL不能指示中间数据库(DB2)在编译阶段遵循数据库链接。因此,为了使此PL/SQL块编译和运行,应在前端数据库DB1上定义dblink1和dblink2两个数据库链接。在运行时,将像预期的那样在DB2中查找数据库链接dblink2。
解决方案:
要实施解决方案,请执行以下步骤:
1.在指向DB3的DB1上创建数据库链接dblink2
SQL> create database link dblink2 connect to u3 identified by u3 using 'EMT102U6';
2.在DB1上创建并编译PL/SQL块。
CREATE DATABASE LINK dblink2 CONNECT TO u3 IDENTIFIED BY u3 USING 'EMT102U6'; SELECT * FROM global_name@dblink2; DECLARE num NUMBER; BEGIN SELECT c1 INTO num FROM syn1; END; / PL/SQL过程成功完成。
提示:另一种选择是在PL/SQL块中使用动态SQL作为解决方法。在使用动态SQL时,数据库链接不会在编译时解析,而是在运行时解析。

我认为引用Oracle文档是好的/可以的,但不应该逐字复制其内容。请提供您自己的示例。 :) - Patrick Bacon
这是对Burleson Consulting答案的很好的补充:http://www.dba-oracle.com/sf_ora_00980_synonym_translation_is_no_longer_valid.htm - Benj

1

解决方法是使用Oracle视图。

CREATE VIEW v_my_synomym as (select * from my_synonym@my_database_link);

然后在您的包或过程中引用该视图,例如:

insert into my_table select * from v_my_synonym;

0

当表/视图/过程的所有者与 SYNONYM 中提到的所有者不匹配时,我发现了这个问题。

例如:如果 TABLE_BRACH 表的所有者是 ownerA,而在 Synonym 中提到的表所有者是其他人(不是 ownerA)。

解决方案: 1. 删除 SYNONYM 2. 使用正确的所有者名称创建相同名称的 SYNONYM。

CREATE PUBLIC SYNONYM BRANCH FOR ownerA.TABLE_BRACH ;

0

需要检查远程数据库授权中与 "my_synonym" 相关的权限,必须对连接字符串中使用的用户几乎具有 "select" 权限,还要检查此同义词指向的对象(可能是有人删除了表)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接