使用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语句,我会在下篇博客分享,谢谢。
全文完。