转载:PL/SQL中ORA-00942错的进一步研究

本文探讨了在PL/SQL开发中遇到ORA-00942错误的原因及解决方案,包括如何正确授权访问Oracle的数据字典视图和动态性能视图。

版权声明: 原创作品,允许转载,转载时请务必以超链接形式标明 文章 原始出处 、作者信息和本声明。否则将追究法律责任。 http://miracle.blog.51cto.com/255044/93450

      对于写某些数据库监控或者编写的过程、函数或包等PL/SQL的对象,如果其中包含ORACLE内部的动态性能试图(DYNAMIC PERFORMANCE VIEW)和数据字典时,常常会遇到如下错误:

    
Error: PL/SQL: ORA-00942: table or view does not exist


      查看一下错误原因:

Cause: The table or view entered does not exist, a synonym that is not allowed here was used, or a view was referenced where a table is required. Existing user tables and views can be listed by querying the data dictionary. Certain privileges may be required to access the table. If an application returned this message, the table the application tried to access does not exist in the database, or the application does not have access to it.

Action: Check each of the following:

the spelling of the table or view name.

that a view is not specified where a table is required.

that an existing table or view name exists.

Contact the database administrator if the table needs to be created or if user or application privileges are required to access the table.

Also, if attempting to access a table or view in another schema, make certain the correct schema is referenced and that access to the object is granted.

  
      但是大家往往都非常愕然,奇怪呀,明明在SQL/PLUS中是可以直接查询的呀,并且返回了结果。但是为什么在编译过程、函数或者包时有错误出现呢?
      其实不然,只能说明我们当前的用户还没有足够的权限。
      那好,就直接授权,使得某个用户可以有确定的查询权限:

    
SQL> grant select on dba_tablespaces to xxx;

Grant succeeded.

SQL> grant select on v$session to xxx;
grant select on v$session to asg
                *
ERROR at line 1:
ORA-02030: can only select from fixed tables/views

     
      进行上述操作,可以看到数据字典(DATA DICTIONARY)可以直接授权,而使用了。但是DYNAMIC PERFORMANCE VIEW却不可以,并且报了ORA-02030的错误。

    
can only select from fixed tables/views

Cause: An attempt is being made to perform an operation other than a retrieval from a fixed table/view.

Action: You may only select rows from fixed tables/views.


      看到了,对于V$SESSION我的授权是有问题的!对,也就是说V$根本不是个VIEWS(如果你说根本不是TABLES,后面的论述就可以不用看了 -:)) 。
      看看ORACLE给出的说明:

     
V$ Views

The actual dynamic performance views are identified by the prefix V_$ . Public synonyms for these views have the prefix V$ . Database administrators and other users should access only the V$ objects, not the V_$ objects.

  
      很显然,V$可以说是个“同义词”!所以会出现授权的错误。
      那么该如何授权呢?对,按照ORACLE给出的规则,按图索骥:

SQL> grant select on v_$session to XXX;

Grant succeeded.


      可以看到授权成功,为了编译成功,我们还要对编写的程序脚本进行轻微的改动,什么?对,就是将V$SESSION改写成SYS.V_$SESSION即 可。
      接下来,再想想,如果我们编写的内容,涉及比较多的DATA DICTIONARY或者是DYNAMIC PERFORMANCE VIEW,我们一个一个授权岂不是很麻烦?
      我们可以通过ORACLE预先定义的角色,一次性完成授权:

     
SQL> grant select any  dictionary to xxx;

Grant succeeded.


     这样,我就可以直接使用DATA DICTIONARY和DYNAMIC PERFORMANCE VIEW。但是,一定要注意,这样的授权对于数据库的安全性来讲是不利的。
     ------------------------
      从ORA-00942开始的问题,我们将问题引申到DYNAMIC PERFORMANCE VIEW和ORACLE SECURITY等方面,确实很有意思。所以说,对于ORACLE的学习,多动手,多读官方文档,多总结总结确实很重要呀。
      技术没有障碍,就看你肯不肯钻 -:)
    



本文出自 “Be the miracle! ” 博客,请务必保留此出处http://miracle.blog.51cto.com/255044/93450

<think>我们正在处理一个Oracle数据库误:误(176,28): PL/SQL: ORA-01775: 同义词的循环链 这个误通常发生在同义词(synonym)的定义中出现了循环引用。例如,同义词A指向同义词B,同义词B又指向同义词A,或者更长的循环链。 解决步骤: 1. 识别循环:需要找出涉及循环的同义词。 2. 打破循环:修改其中一个同义词的定义,使其直接指向基表或视图,而不是另一个同义词。 示例:假设有两个同义词: CREATE SYNONYM syn1 FOR syn2; CREATE SYNONYM syn2 FOR syn1; 这样就形成了一个循环。 如何查找循环? 可以查询数据字典视图`DBA_SYNONYMS`(如果权限允许)或`USER_SYNONYMS`(当前用户的同义词)和`ALL_SYNONYMS`(当前用户有权限的同义词)。 通过递归查询来查找循环,但通常可以通过检查同义词的定义来发现。 一个简单的查询来检查同义词的目标对象是否存在循环: SELECT synonym_name, table_owner, table_name FROM all_synonyms WHERE synonym_name IN ( ... ); --可能需要根据误信息中的同义词名来查 但是,误信息中并没有给出具体的同义词名称,只给出了误位置(176行,28列)。因此,我们需要检查代码中第176行附近使用的对象。 解决建议: 1. 检查代码中第176行引用的对象(可能是表、视图或同义词)。如果它是一个同义词,则检查该同义词指向的对象。 2. 使用如下查询检查同义词链: SELECT s.synonym_name, s.table_owner, s.table_name, (CASE WHEN t.object_type IS NULL THEN 'MISSING' ELSE t.object_type END) AS target_type FROM all_synonyms s LEFT JOIN all_objects t ON s.table_name = t.object_name AND s.table_owner = t.owner WHERE s.synonym_name = '同义词名'; -- 将同义词名替换为实际使用的同义词 3. 如果发现同义词指向另一个同义词,则继续追踪,直到找到基对象或发现循环。 如果权限允许,可以使用以下脚本递归查找同义词链(注意:如果链很长,可能需要递归查询,但Oracle的递归查询深度有限,且循环会导致无限递归,需谨慎)。 另一种方法是尝试删除并重建涉及的同义词,确保它们直接指向基表或视图,而不是其他同义词。 注意:如果循环涉及多个同义词,需要修改其中一个同义词的定义,使其指向实际对象。 由于误发生在PL/SQL代码中,可能是编译存储过程、函数等引用了有循环的同义词。 示例修正: 假设发现同义词A指向同义词B,而同义词B指向同义词A。我们可以修改同义词A,使其直接指向基表: DROP SYNONYM A; CREATE SYNONYM A FOR schema_name.base_table; 然后重新编译出PL/SQL代码。 如果无法确定循环的同义词,可以尝试在误发生的位置(第176行)附近,将使用的对象替换为基表的完全限定名(schema.table_name)来临绕过同义词。 根据以上分析,这给出一个通用的解决步骤,但由于误信息中没有具体同义词名,所以无法提供具体代码。 注意:操作同义词需要相应权限。 由于问题描述中没有给出具体的同义词名称,我们只能提供一般性的指导。 因此,回答如下: </think>### 误分析:ORA-01775 同义词循环链 **误原因** 在 Oracle 中,`ORA-01775: 同义词的循环链` 表示存在 **同义词(synonym)嵌套循环引用**。例如: - 同义词 A 指向同义词 B - 同义词 B 指向同义词 C - 同义词 C **又指回同义词 A** 形成循环依赖后,Oracle 无法解析最终对象。 **解决方法** 1. **定位循环链** 查询数据字典找出循环路径: ```sql SELECT owner, synonym_name, table_owner, table_name FROM dba_synonyms WHERE synonym_name IN ( -- 需替换为实际同义词名 'YOUR_SYNONYM_A', 'YOUR_SYNONYM_B', 'YOUR_SYNONYM_C' ); ``` 2. **打破循环** 修改其中一个同义词的定义,使其直接指向 **基表/视图** 而非其他同义词: ```sql CREATE OR REPLACE SYNONYM YOUR_SYNONYM_A FOR schema_name.actual_base_table; -- 指向真实对象 ``` 3. **验证依赖** 重新编译失效对象: ```sql ALTER PACKAGE your_package_name COMPILE; -- 替换为报对象名 ``` **关键注意事项** - 检查所有级联同义词的最终目标必须是 **非同义词对象**(表/视图) - 避免跨 schema 的同义词嵌套(如 `synA→schemaB.synB→schemaA.synA`) - 使用 `DBA_DEPENDENCIES` 视图分析对象依赖关系: ```sql SELECT * FROM dba_dependencies WHERE referenced_name = '问题同义词名'; ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值