在日常数据库维护过程中,我们会发现数据库中一些对象(包Package、存储过程Procedure、函数Function、视图View、同义词.....)会失效,呈现无效状态(INVALID)。有时候需要定期检查数据库中存在哪些失效对象,对于存在异常的对象需要重新编译,有些自动失效的对象,一般会在下次调用的时候,会被重新编译,所以这些不需要人工干预。那么为什么对象突然会失效呢?又如何快速、高效的编译失效对象呢?哪些失效的对象不需要我们去重新编译呢?

数据库对象失效原因

数据库对象失效的原因很多,下面大致归纳了一些常见的原因(有些漏掉的,希望大家补充):

1: 当被引用对象的结构变更时,都会使得相关的依赖对象转变为INVALID状态。

数据库中的对象(存储过程,函数,包,视图,触发器),它们往往需要直接或者间接的引用其它对象,对象的依赖包括直接和间接二种,其中直接依赖是指存储对象直接依赖于被引用对象,而间接依赖是指对象间接依赖于被引用对象

要查看被引用的对象,可以通过下面SQL查看

select * from dba_dependencies where name='&objectname';

    

select * from all_dependencies where name='&objectname';

 

select * from user_dependencies where name='&objectname';

举个简单例子,视图V_TEST引用了表TEST,TEST表修改了表结构时,会导致视图V_TEST变为无效对象。

SQL> CREATE TABLE TEST ( ID NUMBER(10));

 

Table created.

 

SQL> CREATE VIEW V_TEST AS SELECT * FROM TEST;

 

View created.

 

SQL> SELECT OBJECT_NAME, STATUS FROM DBA_OBJECTS WHERE OBJECT_NAME='V_TEST';

 

OBJECT_NAME STATUS

 

------------------- ----------------

 

V_TEST VALID

 

--修改表结构,增加一个字段NAME后,视图V_TEST变为无效

 

SQL> ALTER TABLE TEST ADD NAME VARCHAR(12);

 

Table altered.

 

SQL> SELECT OBJECT_NAME, STATUS FROM DBA_OBJECTS WHERE OBJECT_NAME='V_TEST';

 

OBJECT_NAME STATUS

 

------------------- ----------------

 

V_TEST INVALID

 

--查询视图V_TEST后,数据库会重新编译视图

 

SQL> SELECT * FROM V_TEST;

 

no rows selected

 

SQL> SELECT OBJECT_NAME, STATUS FROM DBA_OBJECTS WHERE OBJECT_NAME='V_TEST';

 

OBJECT_NAME STATUS

 

------------------- ----------------

 

V_TEST VALID

 

其实不管视图,像存储过程,函数、包等,如果代码本身没有什么错误,只是引用的对象发生了变化。也会失效。但并不影响调用,因为ORACLE在调用时会自动重新编译的,如果其它对象变化后导致编译有错误。这时调用时重新编译后也是错误并处于失效状态,所以调用会出错。

2:发布SQL脚本时(包、存储过程、函数等),没有充分测试,编译时出错,这时对象变为无效。

3: 数据库升级、迁移时,出现大量无效对象(本质原因,个人臆测归结为原因1)。

4: 诸如此类各种情况:例如,Oracle 会自动维护分区索引,对于全局索引,如果在对分区表操作时,没有指定update index,则会导致全局索引失效,需要重建。

编译失效对象的方法

统计失效的对象:

select owner, object_type, status, count(*)

 

from dba_objects

 

  where status='INVALID'

 

group by owner, object_type, status

 

order by owner, object_type

 

查看具体失效对象

col owner for a20;

 

col object_name for a32;

 

col object_type for a16

 

col status for a8

 

select owner, object_name, object_type, status

 

from dba_objects

 

where status='INVALID'

 

order by 1, 2,3;

 

下文大多参考博文Oracle中编译无效的对象常用方法,修改并作了总结、整理

1:   使用ALTER *** COMPLIE语句手工进行编译,这个适用于少数、个别对象失效

alter package <schema name>.<package_name> compile;

alter package <schema name>.<package_name> compile body;

alter view <schema name>.<view_name> compile;

alter trigger <schema).<trigger_name> compile;

2:执行@$ORACLE_HOME/rdbms/admin/utlrp.sql脚本编译数据库失效对象。

许多情况下,由于数据库的升级或迁移,会导致数据库中的对象失效。由于对象之间可能存在复杂的倚赖关系,所以手工编译通常无法顺利通过。通常我们会在Oracle的升级指导中看到这个脚本,Oracle强烈推荐在migration/upgrade/downgrade之后,通过运行此脚本编译失效对象。但是注意,Oracle提醒,此脚本需要用SQLPLUS以SYSDBA身份运行,并且当时数据库中最好不要有活动事物或DDL操作,否则极容易导致死锁的出现(这是很容易理解的)。

Oracle highly recommends running this script towards the end of of any migration/upgrade/downgrade.

另外,utlrp.sql 里面其实调用了$ORACLE_HOME/rdbms/admin/utlrcmp.sql来编译失效对象。

3:ORACLE提供了自动编译的接口dbms_utility.compile_schema(user,false); 调用这个过程就会编译所有失效的过程、函数、触发器、包

exec dbms_utility.compile_schema( 'SCOTT' )

4:  一些网友书写的编译失效对象(经过整理)

SQL 1: 编译失效对象

set heading off; 

set feedback off; 

set echo off; 

Set lines 999; 

 

Spool run_invalid.sql 

 

select 

'ALTER ' || OBJECT_TYPE || ' ' || 

OWNER || '.' || OBJECT_NAME || ' COMPILE;' 

from 

dba_objects 

where 

status = 'INVALID' 

and 

object_type in ('PACKAGE','FUNCTION','PROCEDURE','TRIGGER','JAVA SOURCE','JAVA CLASS','') 

; 

spool off; 

set heading on; 

set feedback on; 

set echo on; 

 

@run_invalid.sql  

SQL 2:在上面的方法中,只能知道某某编译失败,不清楚失败原因,可以用PL/SQL实现更详细的错误信息

DECLARE 

 v_objname        user_objects.object_name%TYPE; 

 v_objtype        user_objects.object_type%TYPE; 

 CURSOR cur IS 

    SELECT object_name,object_type 

      FROM USER_OBJECTS 

     WHERE status = 'INVALID' 

       AND object_type IN ('FUNCTION','JAVA SOURCE','JAVA CLASS','PROCEDURE','PACKAGE','TRIGGER'); 

BEGIN 

 OPEN cur; 

 LOOP 

    FETCH cur into v_objname, v_objtype; 

 

EXIT WHEN cur%NOTFOUND; 

    BEGIN 

      EXECUTE Immediate 'alter ' || v_objtype || ' ' || v_objname||' Compile'; 

      dbms_output.put_line('编译' || v_objtype || ' ' || v_objname || '()成功'); 

    EXCEPTION 

      WHEN OTHERS THEN 

        dbms_output.put_line('编译' || v_objtype ||' ' || v_objname || '()失败.' || SQLERRM); 

    END; 

 END LOOP; 

 CLOSE cur; 

END; 

参考资料:

http://jzhil2004.blog.163.com/blog/static/275585042010117113214172/

http://blog.csdn.net/tianlesoftware/article/details/4843600

http://www.233.com/oracle/jishu/20071014/101911246.html

ORACLE编译失效对象小结的更多相关文章

  1. oracle编译 失效对象方式

    如果procedure 所使用的表结构发生了改变等其它情况,在相应的xxx_objects表的status字段会变为invalid状态,但是如果在调用时procedure会自动编译,grant失效对象 ...

  2. sqlplus编译失效对象

    原文整理自:http://www.51testing.com/?uid-16403-action-viewspace-itemid-98161:http://www.eygle.com/archive ...

  3. oracle 编译无效对象

    在数据库中,会存在一些无效的对象,导致这种现象的发生原因很多,其中最常见的就是数据库升级(例如修改了表的结构),迁移而引起. 编译无效对象的方式: 1 使用alter **** compile 语句进 ...

  4. oracle重新编译失效对像

    重新编译失效对像可执行utlrp.sql文件: SQL> @?/rdbms/admin/utlrp.sql TIMESTAMP --------------------------------- ...

  5. oracle 索引失效原因及解决方法

    oracle 索引失效原因及解决方法 2010年11月26日 星期五 17:10 一.以下的方法会引起索引失效 ‍1,<>2,单独的>,<,(有时会用到,有时不会)3,like ...

  6. oracle 编译中一个关于clntsh 库的一个 帖子 ,收藏!

    oracle 编译中一个关于clntsh 库的一个 帖子 ,收藏! ------------------------------------------------------------------ ...

  7. oracle 索引失效原因

    转自  http://www.cnblogs.com/orientsun/archive/2012/07/05/2577351.html Oracle 索引的目标是避免全表扫描,提高查询效率,但有些时 ...

  8. Oracle 用户、对象权限、系统权限

    --================================ --Oracle 用户.对象权限.系统权限 --================================  一.用户与模式 ...

  9. 能使 Oracle 索引失效的六大限制条件【转】

    . 引用自: http://www.cnblogs.com/orientsun/archive/2012/07/05/2577351.html  总结得非常到位 Oracle 索引的目标是避免全表扫描 ...

随机推荐

  1. C#开发微信公众平台-就这么简单(附Demo)

    写在前面 阅读目录: 服务号和订阅号 URL配置 创建菜单 查询.删除菜单 接受消息 发送消息(图文.菜单事件响应) 示例Demo下载 后记 最近公司在做微信开发,其实就是接口开发,网上找了很多资料, ...

  2. java中List对象列表去重或取出以及排序

    面试碰到几次list的去重和排序.下面介绍一种做法: 1. list去重 1.1 实体类Student List<Student>容量10k以上,要求去重复.这里Student的重复标准是 ...

  3. Struts2 源码分析——配置管理之ContainerProvider接口

    本章简言 上一章笔者讲到关于Dispatcher类的执行action功能,知道了关于执行action需要用到的信息.而本章将会讲到的内容也跟Dispatcher类有关系.那就是配置管理中的Contai ...

  4. UML类图简单介绍

    先上一张图: 概述 类图(Class Diagram)是面向对象系统建模中最常用和最重要的图,是定义其它图的基础.类图主要是用来显示系统中的类.接口以及它们之间的静态结构和关系的一种静态模型. 类图组 ...

  5. ActiveX(二)Js 监听 ActiveX中的事件

    在上一篇随笔:ActiveX(一)第一个简单的Demo 中,已经可以实现 js 单向调用 ActiveX 中的方法,在很多情况下ActiveX中的方法的执行时相对耗时.耗性能的.在这样的情况下.Act ...

  6. WCF入门教程(四)通过Host代码方式来承载服务

    WCF入门教程(四)通过Host代码方式来承载服务 之前已经讲过WCF对外发布服务的具体方式. WCF入门教程(一)简介 Host承载,可以是web,也可以是控制台程序等等.比WebService有更 ...

  7. PetaPoco4.0 实体某个字段不赋值会更新成null解决方案

    最新用PetaPoco4.0做项目发现有个需求,就是比如说:在mvc表单中,只显示部分字段,一个表单还有其他状态等字段,没有显示到mvc页面上 但是当MVC收集表单提交更新的时候,会发现会把数据库中的 ...

  8. web api中的RouteHandler

    ASP.NET MVC4中引入的Web API可以说是进行REST软件开发的利器(个人意见),但是最近在web form中混入web api时,发现一个问题:由于以前的web form项目中,使用到了 ...

  9. System.Diagnostics.Process.Start的妙用

    我们经常会遇到在Winform或是WPF中点击链接或按钮打开某个指定的网址, 或者是需要打开电脑中某个指定的硬盘分区及文件夹, 甚至是"控制面板"相关的东西, 那么如何做呢? 答案 ...

  10. php语言实现的7种基本的排序方法

    今天总结了一下常用的7种排序方法,并用php语言实现. 直接插入排序 /* * 直接插入排序,插入排序的思想是:当前插入位置之前的元素有序, * 若插入当前位置的元素比有序元素最后一个元素大,则什么也 ...