从Oracle里提取出PL/SQL
dbms_metadata工具也可以被用来提取保存在Oracle程序包里的源代码、PL/SQL和Java。使用dbms_metadata,存储过程或者函数也能够被轻易地提取出来。
在Listing D的例子里,我提取出了所有同fred结构描述相关联的过程。
connect fred/flintstone;
spool procedures_punch.lst
select
DBMS_METADATA.GET_DDL('PROCEDURE',u.object_name)
from
user_objects u
where
object_type = 'PROCEDURE';
spool off;
dbms_metadata工具对于提取过程码尤其有用,因为原来所有的格式都被保留下来了。Listing E是dbms_metadata为存储过程所做出的输出。
CREATE OR REPLACE PROCEDURE "SYSTEM"."ORA$_SYS_REP_AUTH" as
i integer;
x integer;
begin
i:=dbms_sql.open_cursor;
dbms_sql.parse(i,'GRANT SELECT ON SYSTEM.repcat$_repschema TO SYS ' ||
'WITH GRANT OPTION',dbms_sql.v7);
x:=dbms_sql.execute(i);
dbms_sql.parse(i,'GRANT SELECT ON SYSTEM.repcat$_repprop TO SYS ' ||
'WITH GRANT OPTION',dbms_sql.v7);
x:=dbms_sql.execute(i);
dbms_sql.parse(i,'GRANT SELECT ON SYSTEM.def$_aqcall TO SYS ' ||
'WITH GRANT OPTION',dbms_sql.v7);
x:=dbms_sql.execute(i);
dbms_sql.parse(i,'GRANT SELECT ON SYSTEM.def$_calldest TO SYS ' ||
'WITH GRANT OPTION',dbms_sql.v7);
x:=dbms_sql.execute(i);
dbms_sql.parse(i,'GRANT SELECT ON SYSTEM.def$_error TO SYS ' ||
'WITH GRANT OPTION',dbms_sql.v7);
x:=dbms_sql.execute(i);
dbms_sql.parse(i,'GRANT SELECT ON SYSTEM.def$_destination TO SYS ' ||
'WITH GRANT OPTION',dbms_sql.v7);
x:=dbms_sql.execute(i);
dbms_sql.close_cursor(i);
exception when others then
if dbms_sql.is_open(i) then
dbms_sql.close_cursor(i);
end if;
raise;
end;
dbms_metadata所存在的问题
同所有Oracle的新工具一样,dbms_metadata也有一些缺点。当你有一些带有外来关键字引用完整性(例如Oracle的references限制)的表格时,按照重新加载到另一个数据库里的正确顺序而使用dbms_metadata来提取表格DDL是非常好的。如果你没有按照外来关键字引用完整性的正确顺序来提取表格,那么就会有一个表格被添加,它会参照另一个还没有被添加表格的表格。进行这项更改将会涉及一个WHERE子句的加入,这个子句会查询dba_constraints和dba_cons_columns,以确定正确的表格顺序。
尽管有这些看得到的缺点,但是dbms_metadata工具在从Oracle里提取DDL和过程代码上不失为一个理想的工具。Oracle未来的发行版会让dbms_metadata更加强大,对此我深信不疑。
