如何制作数据库包的副本

Jef*_*emp 2 oracle plsql

我有一个包(可能很多),我想将其复制到具有不同名称的新包中。

理想情况下,我想运行这个:

begin
  copy_package('MY_PACKAGE_NAME','MY_PACKAGE_NAME$BK');
end;
/
Run Code Online (Sandbox Code Playgroud)

这将找到名为 的包MY_PACKAGE_NAME,并创建/替换一个名为 的新包,MY_PACKAGE_NAME$BK其中所有引用MY_PACKAGE_NAME(如果有)也已更改。

假设包名称不区分大小写是合理的,并且源中对包名称的任何引用都将全部为大写或全部小写(即My_Package_Name源中不会有任何引用)。

Jef*_*emp 5

此过程将复制指定的包,同时替换对包名称(全部大写或小写)的任何引用 - 包括注释中的任何引用。

procedure copy_package
  (old_name IN VARCHAR2
  ,new_name IN VARCHAR2
  ) is
  ddl clob;
begin
  ddl := dbms_metadata.get_ddl
    (object_type => 'PACKAGE_SPEC'
    ,name => old_name
    );
  ddl := REPLACE(ddl, UPPER(old_name), UPPER(new_name));
  ddl := REPLACE(ddl, LOWER(old_name), LOWER(new_name));
  EXECUTE IMMEDIATE ddl;
  ddl := dbms_metadata.get_ddl
    (object_type => 'PACKAGE_BODY'
    ,name => old_name);
  ddl := REPLACE(ddl, UPPER(old_name), UPPER(new_name));
  ddl := REPLACE(ddl, LOWER(old_name), LOWER(new_name));
  EXECUTE IMMEDIATE ddl;
end copy_package;
Run Code Online (Sandbox Code Playgroud)

如果模式中已经存在新的包名称,它将在没有警告的情况下被覆盖。

旧包保持原样。

如果需要任何授权或同义词,则不会复制它们。

如果包的代码碰巧在更长的标识符(例如NOT_MY_PACKAGE_NAME)中包含包名称,这将失败,因为它将不加选择地替换该文本。

如果包规格或主体的大小大于 32K,则此过程将失败。

如果未找到包规范或正文,则此过程会引发 ORA-31603。如果找到了规范但没有找到正文,则将复制规范,然后引发异常。