表更改后 Oracle SQL 过程变得无效

Posted

技术标签:

【中文标题】表更改后 Oracle SQL 过程变得无效【英文标题】:Oracle SQL procedure getting invalid after table alter 【发布时间】:2021-08-25 05:55:28 【问题描述】:

当试图改变一个表时,只有选择语句的过程之一变得无效。 表格脚本:

    create table t1(a number,b number);

    create or replace procedure p1
    is
    x number;
    y  number;
    begin
    select a,b into x,y from t1;
    end;
    /

    create or replace procedure p2(i number)
    is
    x number;
    y  number;
    begin
    select a,b into x,y from t1 where i=1;
    end;
    /

    alter table t1 add (d number);

    select object_name,status from dba_objects where object_name in ('T','P1','P2');

    T   VALID
    P1  VALID
    P2  INVALID

观察到,当过程接受参数时,如果我们在 select 语句中使用它,对象就会变得无效,否则它不会变得无效。

是否可以在程序无效的情况下更改表?

【问题讨论】:

this 有帮助吗? 【参考方案1】:

实际上,您的对象并非真的无效。当您的第二个过程包含一个 where 子句,该子句根据规则在字典中产生无效时,就会出现此问题。

如果您运行该程序,它将自动生效。

演示

甲骨文 19c

SQL> alter session set current_schema=test1 ;

Session altered.

SQL> create table t1(a number,b number);

Table created.

SQL> create or replace procedure p1
    is
    x number;
    y  number;
    begin
    select a,b into x,y from t1;
    end;
    /  2    3    4    5    6    7    8

Procedure created.

SQL> create or replace procedure p2(i number)
    is
    x number;
    y  number;
    begin
    select a,b into x,y from t1 where i=1;
    end;
    /
  2    3    4    5    6    7    8
Procedure created.

SQL>  alter table t1 add (d number);

Table altered.

SQL> select object_name,status from dba_objects where object_name in ('T1','P1','P2') and owner='TEST1' ;

OBJECT_NAME               STATUS
------------------------- --------------------
P1                        VALID
P2                        INVALID
T1                        VALID

现在,如果程序确实无效,您将无法执行它。让我们在您的表中插入一行并尝试运行它。

SQL> insert into t1 values ( 1 ,1 ,1) ;

1 row created.

SQL> commit ;

Commit complete.

SQL> set serveroutput on
SQL> exec p2 ( i=>1 ) ;

PL/SQL procedure successfully completed.

SQL> select object_name,status from dba_objects where object_name in ('T','P1','P2') and owner='TEST1' ;

OBJECT_NAME               STATUS
------------------------- --------------------
P1                        VALID
P2                        VALID
T1                        VALID

有一些内部规则定义了字典中对象的失效,例如过程、函数或包,当它们所依赖的对象发生某些更改时。

在这种特定情况下,并没有真正的失效,因为对象只是在执行 DDL 后在字典中被标记为无效。

第一个不是无效的原因是因为它不包含任何where子句,而只是检索两个现有的列。第二个变得无效,因为它包含 PLSQL 变量的 where 子句。见下文

https://docs.oracle.com/cd/E24693_01/appdev.11203/e17125/adfns_dependencies.htm#CHDJIIFC

【讨论】:

感谢 roberto 的清晰解释但我们被卡住了,因为我们的对象被高度访问,并且可能在部署期间导致库缓存锁定 library cache lock 是什么意思?那些不是真的无效的对象,一旦你执行它们就会变得有效。,

以上是关于表更改后 Oracle SQL 过程变得无效的主要内容,如果未能解决你的问题,请参考以下文章

oracle带参数的存储过程,一直提示sql无效sql语句。求高手指点

SQL Server存储过程中使用表值作为输入参数示例

oracle存储过程对象无效

Oracle 中的触发器无效

从 SQL 存储过程创建/更改

我用plsql创建的存储过程为啥是无效的?