重命名一张表后避免重新编译程序包

时间:2018-10-01 18:53:50

标签: oracle oracle11g

如何在线重命名内部表(将表test_table重命名为test_table_new)到包内部表(pkg_test)时不解包(pkg_test)。 除此之外,还有一个Web服务会不断查询该程序包,并在使用时将其阻止。

解决方案之一是使用命令“ alter package pkg_test compile”,但问题是Web服务已经采用了该软件包(pkg_test),并且不允许执行该操作。

2 个答案:

答案 0 :(得分:0)

嗯,我能想到的正确方法是:不要那样做。如果重命名了程序包使用的表,则该程序包将无效,并且必须先解决错误,然后才能使用它。

为什么要重命名表?它有什么好处?

如果可能,将使用TEST_TABLE的代码移动到动态SQL中。这样做,程序包不会失效,但是您仍将无法使用引用重命名表的代码。这是一个示例:

创建示例表和包(没什么花样):

SQL> create table test (datum date);

Table created.

SQL> insert into test values (sysdate);

1 row created.

SQL> create or replace package pkg_test as
  2    function f_right_now return date;
  3    function f_max_datum return date;
  4  end;
  5  /

Package created.

SQL> create or replace package body pkg_test as
  2    function f_right_now return date is
  3    begin
  4      return sysdate;
  5    end;
  6
  7    function f_max_datum return date is
  8      retval date;
  9    begin
 10      select max(datum)
 11      into retval
 12      from test;
 13      return retval;
 14    end;
 15  end;
 16  /

Package body created.

SQL>

让我们看看它是否有效:

SQL> select pkg_test.f_right_now, pkg_test.f_max_datum from dual;

F_RIGHT_NO F_MAX_DATU
---------- ----------
2018-10-01 2018-10-01

SQL> select object_type, status from user_objects where object_name = 'PKG_TEST';

OBJECT_TYPE         STATUS
------------------- -------
PACKAGE             VALID
PACKAGE BODY        VALID

到目前为止,太好了。现在,重命名表并再次检查包状态:

SQL> rename test to test_new;

Table renamed.

SQL> select object_type, status from user_objects where object_name = 'PKG_TEST';

OBJECT_TYPE         STATUS
------------------- -------
PACKAGE             VALID
PACKAGE BODY        INVALID

SQL> select pkg_test.f_right_now, pkg_test.f_max_datum from dual;
select pkg_test.f_right_now, pkg_test.f_max_datum from dual
                                                       *
ERROR at line 1:
ORA-04063: package body "SCOTT.PKG_TEST" has errors


SQL>

按预期-程序包主体现在无效,您不能使用它。因此,让我们切换到动态SQL:

SQL> create or replace package body pkg_test as
  2    function f_right_now return date is
  3    begin
  4      return sysdate;
  5    end;
  6
  7    function f_max_datum return date is
  8      retval date;
  9    begin
 10      execute immediate 'select max(datum) from test' into retval;
 11      return retval;
 12    end;
 13  end;
 14  /

Package body created.

SQL>

看到了吗?尽管表TEST不再存在,Oracle也不抱怨。包裹状态为有效:

SQL> select object_type, status from user_objects where object_name = 'PKG_TEST';

OBJECT_TYPE         STATUS
------------------- -------
PACKAGE             VALID
PACKAGE BODY        VALID

但是您不能使用“无效”功能(而“正确”功能仍然有效):

SQL> select pkg_test.f_right_now, pkg_test.f_max_datum from dual;
select pkg_test.f_right_now, pkg_test.f_max_datum from dual
                             *
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "SCOTT.PKG_TEST", line 10


SQL> select pkg_test.f_right_now from dual;

F_RIGHT_NO
----------
2018-10-01

SQL>

SQL> select pkg_test.f_right_now, pkg_test.f_max_datum from dual;
select pkg_test.f_right_now, pkg_test.f_max_datum from dual
                             *
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "SCOTT.PKG_TEST", line 10


SQL>

再重命名?当然可以,为什么不呢?

SQL> rename test_new to test_littlefoot;

Table renamed.

SQL> select object_type, status from user_objects where object_name = 'PKG_TEST';

OBJECT_TYPE         STATUS
------------------- -------
PACKAGE             VALID
PACKAGE BODY        VALID

SQL> select pkg_test.f_right_now from dual;

F_RIGHT_NO
----------
2018-10-01

SQL> select pkg_test.f_max_datum from dual;
select pkg_test.f_max_datum from dual
       *
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "SCOTT.PKG_TEST", line 10

因此,请参见动态SQL为您工作。我认为(再次)-不要“仅因为”重命名表,您应该有充分的理由这样做。

答案 1 :(得分:0)

感谢您的帮助

由于使用重命名的速度快,因此Web服务可以在线查询该表,所以我要做的是首先加载一个临时表(dws.temp),然后将该临时表重命名为原始表。 Web服务使用的表(dws .finally)。

另一种方法是直接加载到原始表(dws.finally),但是根据情况,这可能会延迟,并且要求表(dws.finally)的更新以秒为单位。重新命名后,我在一秒钟内更新了表

注意:Web服务通过包消耗了原始表(dws.finally),因此当我重命名(dws.temp到dws.finally)时,它将被反编译并且Web服务显示错误。

也可以尝试使用动态SQL,但是开发成本更高