ORA-00980 同义词翻译在 PLSQL 中不再有效

ORA-00980 synonym translation no longer valid in PLSQL

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

insert into my_table select * from my_synonym@my_database_link;

如果我把上面的语句放到一个PLSQL块中,它不会编译,给出错误信息"ORA-00980: synonym translation is no longer valid"。标准解释是同义词指向的 table 已被删除等,但事实并非如此,因为该语句适用于 SQL.

如果某些东西在 SQL 中有效但在 PL/SQL 中无效,那么在大多数情况下这是权限问题。

当您进入 PL/SQL 块时,用户通过 角色 获得的任何特权都不会激活。所以很可能底层 table 的 SELECT 特权是通过角色授予的,因此在 PL/SQL 块中不是 "active"。

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

检查 "my_synonym" 的远程数据库授权对于您在连接字符串中使用的用户必须几乎 "select",还要检查此同义词指向的对象(也许有人删除了 table).

感谢所有试图提供帮助的人。结果证明这是一个 Oracle 限制:

https://support.oracle.com/rs?type=doc&id=453754.1

APPLIES TO:

PL/SQL - Version 9.2.0.8 and later Information in this document applies to any platform. Checked for relevance on 01-Apr-2015

SYMPTOMS

A PL/SQL block fails with error: ORA-00980: synonym translation is no longer valid, when selecting data from a remote database. The following code demonstrates this issue:

On DB3 (create the table)

CONNECT u3/u3 DROP TABLE tab; CREATE TABLE tab(c1 number); INSERT INTO tab VALUES (1); COMMIT;

On DB2 (create a synonym to the table on 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;

On DB1 (create a synonym to the synonym on 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;

This works in SQL but fails when called from PL/SQL

DECLARE num NUMBER; BEGIN SELECT c1 INTO num FROM syn1; END; /

ERROR at line 4: ORA-06550: line 4, column 3: PL/SQL: ORA-00980: synonym translation is no longer valid ORA-06550: line 4, column 3: PL/SQL: SQL Statement ignored

CAUSE

This issue was reported in Bug 2829591 QUERING FROM A PL/SQL PROCEDURE IN 9I -> 8I-> 7.3.4, GETTING ORA-980. This bug was closed as 'NOT A BUG' for the following reasons

PL/SQL cannot instruct middle database (DB2) to follow the database link during the compilation phase. Therefore in order for this PL/SQL block to compile and run, both database links dblink1 and dblink2 should be defined on the front end database - DB1. During runtime database link dblink2 will be looked up in DB2 as expected.

SOLUTION

To implement the solution, please execute the following steps:

  1. Create a database link dblink2 on DB1 pointing to DB3

SQL> create database link dblink2 connect to u3 identified by u3 using 'EMT102U6';

  1. Create and compile the PL/SQL block on DB1.

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 procedure successfully completed.

TIP: Another option is to use dyanmic SQL in the PL/SQL block as a work around. When using dynamic SQL the database link is not resolved at compile time but at runtime.

当 table/view/procedure 的所有者与 SYNONYM 中提到的所有者不匹配时,我发现了这个问题。

示例:如果 table TABLE_BRACH 的所有者是所有者 A,并且在同义词中提到 table 所有者是其他人(不是所有者 A)。

解决方法: 1. 去掉同义词 2. 用正确的所有者创建同名的。

CREATE PUBLIC SYNONYM BRANCH FOR ownerA.TABLE_BRACH ;

解决方法是改用 Oracle 视图。

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

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

insert into my_table select * from v_my_synonym;