使用dbms_detadata.get_ddl导出表结构

     今天在测试怎样导出用户的视图时候,使用了dbms_metadata.get_ddl,特此记录,首先带上参考的链接:

    

http://blog.itpub.net/498744/viewspace-277830/
http://blog.sina.com.cn/s/blog_4f86237e010081td.html
http://www.astral-consultancy.co.uk/cgi-bin/hunbug/doco.cgi?11070

    一开始我使用itpub一文中使用的脚本(他的脚本中要求表名大写,我修改了):

   

create or replace procedure proc_dbmsddl_singleobject(p_type varchar2,p_name varchar2,p_filename varchar2) is
begin
  declare
    l_file           utl_file.file_type;
    l_buffer       varchar2(100);
    l_amount    binary_integer := 100;
    l_pos          integer := 1;
    l_clob         clob;
    l_clob_len  integer;
  begin
    select dbms_metadata.get_ddl(upper(p_type),upper(p_name))||';' into l_clob from dual;
    l_clob_len := dbms_lob.getlength(l_clob);
    l_file := utl_file.fopen('ORADIR_F_DIR', p_filename||'.sql', 'a', 2000);  
    while l_pos < l_clob_len loop
      dbms_lob.read(l_clob, l_amount, l_pos, l_buffer);
      utl_file.put_line(l_file, l_buffer);
      l_pos := l_pos + l_amount;
    end loop;
    utl_file.fclose(l_file);
  end;
end proc_dbmsddl_singleobject;

   

create or replace procedure proc_exportddl_allobject(p_filename varchar2) is
begin
  for x in (select table_name from user_tables) loop
       proc_dbmsddl_singleobject('TABLE',x.table_name,p_filename);
  end loop;
/*  for x in (select index_name from user_indexes) loop
       proc_exportddl_singleobject('INDEX',x.index_name,p_filename);
  end loop;
  for x in (select view_name from user_views) loop
       proc_exportddl_singleobject('VIEW',x.view_name,p_filename);
  end loop;
  for x in (select synonym_name from user_synonyms) loop
       proc_exportddl_singleobject('SYNONYM',x.synonym_name,p_filename);
  end loop;*/
end proc_exportddl_allobject;

    为什么我要把上面导view的注释掉呢,因为我只有3个视图,测试没什么意思,表很多,就拿导出表结构测试,测试结果是:

   

    ora-06502 pl/sql 数字或值错误 字符串缓冲区太小,一看就是分配的100太小了,改成1000测试,导出成功,导出数据有44K。

    继续使用另一个脚本测试下:

   

set pagesize 0
set long 90000
set feedback off
set echo off
spool f:/saveFile/oracle/tmd_table.sql
SELECT DBMS_METADATA.GET_DDL('TABLE',u.table_name) FROM USER_TABLES u;
spool off;

    导出结果是44k。

    那把1000改大写试下或者把pl/sql脚本中的90000改小点结果怎样呢:

   

create or replace procedure proc_exportddl_singleobject(p_type varchar2,p_name varchar2,p_filename varchar2) is
begin
  declare
    l_file          utl_file.file_type;
    l_buffer        varchar2(32767);
    l_amount        binary_integer := 32767;
    l_pos          integer := 1;
    l_clob         clob;
    l_clob_len  integer;
  begin
    select dbms_metadata.get_ddl(upper(p_type),upper(p_name))||';' into l_clob from dual;
    l_clob_len := dbms_lob.getlength(l_clob);
    l_file := utl_file.fopen('ORADIR_F_DIR', p_filename||'.sql', 'a', 32767);  
    while l_pos < l_clob_len loop
      dbms_lob.read(l_clob, l_amount, l_pos, l_buffer);
      utl_file.put_line(l_file, l_buffer);
      l_pos := l_pos + l_amount;
    end loop;
    utl_file.fclose(l_file);
  end;
end proc_exportddl_singleobject;

    改成了32767,结果是44k,和上面的44k比对结果

   

     可以看出使用spool导出的结果没有逗号。

     把spool脚本中的90000改小点试下:

    

set pagesize 0
set long 1000
set feedback off
set echo off
spool f:/saveFile/oracle/tmd_table_1000.sql
SELECT DBMS_METADATA.GET_DDL('TABLE',u.table_name) FROM USER_TABLES u;
spool off;

    结果是42k,变小了,把1000去掉:

   

set pagesize 0
set feedback off
set echo off
spool f:/saveFile/oracle/tmd_table_no.sql
SELECT DBMS_METADATA.GET_DDL('TABLE',u.table_name) FROM USER_TABLES u;
spool off;

    结果也是42k,比对下44k和42k的结果:

   

   可以看出42k数据中明显少了数据,44k结果才是正确的。

   这里说明下long参数的意义:

  

long:数据类型用于定义变长字符串,类似于VARCHAR2数据类型,但其字符串的最大长度为32760字节

    所以,在直接使用spool保存查询结果时候,建议把long设置大一些。

    这里可以看出导出的表结构不是我们想要的那种很简单的create语句,里面有storage信息,如何导出表的create语句或者insert语句,我会在下篇博客分享,谢谢。

    全文完。

    

猜你喜欢

转载自53873039oycg.iteye.com/blog/2020452
今日推荐