在Oracle过程中运行DDL - ORA-06508 - 如何在运行时重新编译?

时间:2012-12-06 07:25:47

标签: oracle plsql procedure ddl

我有一个oracle程序,它调用了很少的其他程序。

PROCEDURE1
  过程2
  PROCEDURE3
  ..

现在发生的事情是PROCEDURE2正在对后续程序3及之后使用的某些从属表执行DDL(EXECUTE IMMEDIATE 'DDL PROCESS')。这样可以正常运行,直到它PROCEDURE3投掷ORA-06508 - Program / Unit being called not found

我们不能修改它不使用DDL,我们必须使用它们。我在DDL语句之后尝试重新编译,但它在ALTER PROCEDURE PROCEDURE3 RECOMPILEPROCEDURE1中都不起作用(PROCEDURE2)。

我怀疑PROCEDURE1本身是无效的,并且编译在运行时会导致无限循环。我试过了,不行。

所以我需要使用一些技巧,可以在依赖对象上完成DDL后,在运行时再次使这些过程有效。

提前感谢参与回答的人。

3 个答案:

答案 0 :(得分:2)

在这种情况下,与许多其他情况一样,最好是创建一个包而不是一堆独立的过程。包打破依赖链。这是一个例子:

    SQL> create table tb_t(
     2    col1 number
     3  )
     4  ;

    Table created
  1. 独立程序

    SQL> create or replace procedure Proc1
      2  is
      3  begin
      4    execute immediate 'alter table tb_t add (col2 number)';
      5  end;
      6  /
    

    创建了程序

    SQL> create or replace procedure Proc2
     2  is
     3    l_var number;
     4  begin
     5    select count(*)
     6      into l_var
     7      from tb_t;
     8    dbms_output.put_line(to_char(l_var));
     9  end;
     10  /
    
     Procedure created
    
     SQL> begin
      2    proc1;
      3    proc2;
      4  end;
      5  /
    
  2. 我们正在

         ORA-06508: PL/SQL: could not find program unit being called
    
    1. 封装

      SQL> create or replace package test_pkg
        2  is
        3    procedure proc1;
        4    procedure proc2;
        5  end;
        6  /
      
      Package created
      
      SQL> create or replace package body test_pkg
        2  is
        3    procedure proc1
        4    is
        5    begin
        6      execute immediate 'alter table tb_t add (col3 number)';
        7    end;
        8  
        9    procedure proc2
       10    is
       11     l_var number;
       12    begin
       13      select count(*)
       14        into l_var
       15        from tb_t;
       16      dbms_output.put_line(to_char(l_var));
       17    end;
       18  
       19  end;
       20  /
      
       Package body created
      
      
       SQL> begin
         2    test_pkg.proc1;
         3    test_pkg.proc2;
         4  end;
         5  /
      
         0
      
         PL/SQL procedure successfully completed
      

答案 1 :(得分:0)

alter procedure PX3 compile; -- not "recompile"

这可以按预期工作:

set serveroutput ON

create table X as select 42 A from DUAL;

create procedure PX3
as
  a int;
begin
  select max(A) into a from X;
  dbms_output.put_line(a);
end;
/

create procedure PX2
as
begin
  execute immediate 'alter table X add (B int)';
  execute immediate 'alter procedure PX3 compile';
  PX3;
end;
/

create procedure PX1
as
begin
  PX2;
end;
/

begin
  PX1;
end;
/

drop procedure PX1;
drop procedure PX2;
drop procedure PX3;
drop table X;

答案 2 :(得分:0)

如果我没弄错的话,与Oracle> = 10相比,Oracle 9对依赖和失效更为严格。

我在Oracle 9中有一些程序和/或程序包在他们依赖的表上执行DDL。 我得出的结论是,最实用的解决方案是让它们依赖于这些表。 即而不是做静态SQL

select COL1 into my_var from MY_CHANGING_TABLE ...;

将其作为动态SQL

execute immediate 'select COL1 from MY_CHANGING_TABLE ...' into my_var;