加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

用PlSql导出数据到Excel文件

(2008-08-27 11:06:31)
标签:

it

分类: 数据库专题
问题:写一个存储过程(OUT_FILE2XLS)动态的导出Oracle中指定表的数据
    Example:
        OUT_FILE2XLS("student");则导出student表到STUDENT.XLS文件
        OUT_FILE2XLS("course");则导出couse表到COURSE.XLS文件
关键词:动态Sql、数据字典、Plsql文件读写
平台:windows2000,oracle10g
解决方案:
写两个Procedure一个完成把传入的数据写入文件,另一个负责根据表名生成数据:
1.在具体实现之前我們创建一个文件存放的目录:
  CREATE OR REPLACE DIRECTORY TEST AS 'C:\TEST';
  创建一个名为TEST的目录它的路径为'C:\TEST',当然這是数据库所在的文件系统。
2.FILE_WRITE:
  功能:把传入的varchar2写入文件中
  参数:i_title in varchar2文件名
     i_fileMsg in varchar2待写入文件中的内容
     i_fileType in varchar2文件类型既文件扩展名(无实际意义)
  实现代码:
  'CREATE OR REPLACE PROCEDURE FILE_WRITE(i_title   VARCHAR2,' || chr(10) ||
                                       i_fileMsg VARCHAR2,' || chr(10) ||
                                       i_fileType VARCHAR2) IS' || chr(10) ||
  v_file     UTL_FILE.FILE_TYPE; --文件引用' || chr(10) ||
  PATH       VARCHAR2(1024);' || chr(10) ||
  v_fileName VARCHAR2(2048);' || chr(10) ||
 'BEGIN' || chr(10) ||
  PATH       := "TEST"; --文件写入的目录名' || chr(10) ||
  v_fileName := i_title || '''' . '''' || i_fileType;' || chr(10) ||
  IF UTL_FILE.IS_OPEN(v_file) THEN' || chr(10) ||
    UTL_FILE.FCLOSE(v_file);' || chr(10) ||
  END IF;' || chr(10) ||
  v_file := UTL_FILE.FOPEN(PATH, v_fileName, '''' w '''');' || chr(10) ||
  UTL_FILE.PUT_LINE(v_file, i_fileMsg);' || chr(10) ||
  UTL_FILE.FCLOSE(v_file);' || chr(10) ||
 'EXCEPTION' || chr(10) ||
  WHEN OTHERS THEN' || chr(10) ||
    DBMS_OUTPUT.PUT_LINE(SQLERRM); --写入数据' || chr(10) ||
    IF UTL_FILE.IS_OPEN(v_file) THEN' || chr(10) ||
      UTL_FILE.FCLOSE(v_file);' || chr(10) ||
    END IF;' || chr(10) ||
 'END FILE_WRITE;';
 在这个Procedure中调用UTL_FILE中的UTL_FILE.FOPEN创建文件,UTL_FILE.PUT_LINE写数据到文件。
3.OUT_FILE2XLS
 功能:根据的varchar2(表名)生成数据,并调用前面定义的FILE_WRITE把生成的数据写入文件。
 参数:tName in varchar2表名
 实现代码:
 'CREATE OR REPLACE PROCEDURE OUT_FILE2XLS(tName in varchar2) AS' || chr(10) ||
  v_fileMsg VARCHAR2(30000) := '''''''';' || chr(10) ||
  sqlstr    varchar2(1000);' || chr(10) ||
  type c_type is ref cursor;' || chr(10) ||
  c1 c_type;' || chr(10) ||
  r1 varchar2(30);' || chr(10) ||
  c2 c_type;' || chr(10) ||
  r2 varchar2(1000);' || chr(10) ||
 'BEGIN' || chr(10) ||
  open c1 for ''''' || chr(10) ||
    select COLUMN_NAME' || chr(10) ||
      from all_tab_columns' || chr(10) ||
     where TABLE_NAME = upper(:1) '''' using tName; --动态cursor' || chr(10) ||
  sqlstr := '''' select '''';' || chr(10) ||
  fetch c1' || chr(10) ||
    into r1;' || chr(10) ||
  sqlstr := sqlstr || r1;' || chr(10) ||
  loop' || chr(10) ||
    fetch c1' || chr(10) ||
      into r1;' || chr(10) ||
    exit when c1%notfound;' || chr(10) ||
    sqlstr := sqlstr || '''' || chr(9) || '''' || r1; --excel数据文件的列之间用一个Tab(chr(9))分隔' || chr(10) ||
  end loop;' || chr(10) ||
  close c1;' || chr(10) ||
  sqlstr := sqlstr || '''' from '''' || tName;' || chr(10) ||
  open c2 for sqlstr;' || chr(10) ||
  fetch c2' || chr(10) ||
    into r2;' || chr(10) ||
  if c2%found then' || chr(10) ||
    v_fileMsg := v_fileMsg || r2;' || chr(10) ||
  end if;' || chr(10) ||
  loop' || chr(10) ||
    fetch c2' || chr(10) ||
      into r2;' || chr(10) ||
    exit when c2%notfound;' || chr(10) ||
    v_fileMsg := v_fileMsg || chr(10) || r2; --excel的行之间用一个回车(chr(10))分隔' || chr(10) ||
  end loop;' || chr(10) ||
  FILE_WRITE(upper(tName), v_fileMsg, '''' XLS ''''); --调用FILE_WRITE写入文件' || chr(10) ||
  CLOSE c2;' || chr(10) ||
 'EXCEPTION' || chr(10) ||
  WHEN OTHERS THEN' || chr(10) ||
    NULL;' || chr(10) ||
 'END;';
 这里用到了动态cursor,oracle系统的数据字典all_tab_columns其中存储了表名和它的表结构信息,也就是通过這张表来完成动态查询的。
  好了,在sql plus在运行 exec OUT_FILE2XLS('tableName')文件就生了。('tableName'为你的表名)

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有