现在有个需求,  要求编写oracle存储过程生成Excel文件到指定目录,  但是oracle自己的API貌似不太给力,  所以只能通过另一种更强大的语言来实现了  ——Java。有一个Java框架叫POI,处理Excel起来非常好用,现在我把过程记录下来:

一、下载POI的jar包

我的测试数据库的版本是11g, 所以下载的jar包不能太新,否则导入jar包的时候会报版本错误, 但又产生了一个问题,旧版本的jar包当然功能不是很全,包括我之前比较看重的给Excel加密的功能。之前为了这个功能试了很多版本,都不理想,只能放弃了,不知道oracle 12c版本会怎样,以后再试吧。。。

步入正题,我们的jar包尽可能要新一些,那么,我们要先看看oracle 11g的Java版本:

[oracle@centos6 bin]$ cd $ORACLE_HOME/jdk/bin/
[oracle@centos6 bin]$ javac -version
javac 1.5.0_17

javac的版本是1.5,那么导入的jar包不能是1.6及以上版本编译的。好吧,经过不懈努力,我下载了3.0.1版本的POI的jar包,

POI的历史版本可以根据下面的链接下载:

https://archive.apache.org/dist/poi/release/bin/

二、导入POI的jar包到数据库

1.把jar包上传到服务器的一个目录,我这里是/java/目录:

2.给用户授权:

普通oracle用户要操作Java,必须通过sys授予JAVASYSPRIV权限:

GRANT JAVASYSPRIV TO SCOTT;

3.cd到上传目录,通过loadjava 命令导入oracle数据库:

loadjava的基本语法:

loadjava {-user | -u} username/password[@database]
[option ...] filename [filename] ...

具体选项请参考其他资料,这里不再赘述。

我分别用如下命令导入:

loadjava -r -f -o -user scott/tiger@cat poi-3.0.1-FINAL-20070705.jar

loadjava -r -f -o -user scott/tiger@cat poi-contrib-3.0.1-FINAL-20070705.jar

loadjava -r -f -o -user scott/tiger@cat poi-scratchpad-3.0.1-FINAL-20070705.jar

如图所示,这么老的版本导入的时候还是会报错,不过没有关系,报错的都是本例用不着的类,要是用现在最新版本的话,就没这么幸运了╮(╯▽╰)╭

我们可以用SQL查询一下导入的情况:

SELECT OBJECT_NAME,
DBMS_JAVA.LONGNAME(OBJECT_NAME) JAVA_CLASS_NAME,
O.STATUS
FROM USER_OBJECTS O
WHERE OBJECT_TYPE LIKE 'JAVA CLASS';

通过拼写SQL的方式,生成无效的类的删除语句:

SELECT 'execute immediate ''drop JAVA CLASS "' || OBJECT_NAME || '"'';'
FROM USER_OBJECTS O
WHERE OBJECT_TYPE LIKE 'JAVA CLASS'
AND O.STATUS <> 'VALID';

把生成的语句执行,就删除了没用的而且无效的类了:

BEGIN
EXECUTE IMMEDIATE 'drop JAVA CLASS "/5e316ace_CommonsLogger"';
EXECUTE IMMEDIATE 'drop JAVA CLASS "/eb16769d_HSSFCellUtil"';
EXECUTE IMMEDIATE 'drop JAVA CLASS "/ff8d85a1_HSSFRegionUtil"';
END;

 

三、编写Java生成Excel程序,创建JAVA SOURCE

在这里我写了一个通用的Java类,只要对方法传入SQL字符串和文件路径及名称组成的字符串这两个参数就可以完成功能,代码如下,并把它放到

PL/SQL Developer中创建Java Source:

create or replace and compile java source named createexcel as
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement; import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; public class CreateExcel { private static HSSFWorkbook wb;
private static HSSFSheet sheet;
private static String connStr = "jdbc:oracle:thin:@192.168.*.*:1521:cat";
private static String userStr = "scott";
private static String pwdStr = "tiger"; //@SuppressWarnings("deprecation")
public static void CreateExcel2003(String sql, String fileDir) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
int rowNum = 0; try {
Class.forName("oracle.jdbc.OracleDriver");
conn = DriverManager.getConnection(connStr, userStr, pwdStr);
stmt = conn.createStatement();
rs = stmt.executeQuery(sql); //创建题头
if (rs.next()) {
wb = new HSSFWorkbook();
sheet = wb.createSheet("Result");// 建立新的sheet对象 // 题头字体样式
HSSFFont font = wb.createFont();
font.setFontName("黑体");
font.setFontHeightInPoints((short) 12);// 设置字体大小
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);// 粗体显示
HSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setFont(font); HSSFRow row = sheet.createRow(rowNum);
// 获取列数和列名
ResultSetMetaData rsMetaData = rs.getMetaData();
int numberOfColumns = rsMetaData.getColumnCount();
//System.out.println(numberOfColumns);
HSSFCell[] cells = new HSSFCell[numberOfColumns];
// 根据列数获取列名题头
for (int i = 0; i < numberOfColumns; i++) {
cells[i] = row.createCell((short) i);
cells[i].setCellValue(rsMetaData.getColumnName(i+1));
cells[i].setCellStyle(cellStyle);
}
} //数据行样式
HSSFCellStyle cellStyle1 = wb.createCellStyle(); //创建数据行
while(rs.next()){
rowNum ++;
HSSFRow row = sheet.createRow(rowNum);// 建立新行
// 获取列数
ResultSetMetaData rsMetaData = rs.getMetaData();
int numberOfColumns = rsMetaData.getColumnCount();
HSSFCell[] cells = new HSSFCell[numberOfColumns];
// 获取数据
for (int i = 0; i < numberOfColumns; i++) {
cells[i] = row.createCell((short) i);
cells[i].setCellValue(rs.getString(i+1));
cells[i].setCellStyle(cellStyle1);
// 自动调整列宽
sheet.autoSizeColumn((short) i);
} // for (int i = 0; i < numberOfColumns; i++) {
// // 自动调整列宽
// sheet.autoSizeColumn((short) i);
// }
} FileOutputStream fileOut = new FileOutputStream(fileDir);
wb.write(fileOut);
fileOut.close(); } catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
} } }

四、创建调用Java代码的存储过程

定义的存储过程开头是一样的,唯一不同的就是 “AS LANGUAGE ”后面的语法:

{IS | AS} LANGUAGE JAVA
NAME 'method_fullname (java_type[, java_type]...)
[return java_type]';

我这里是:

CREATE OR REPLACE PROCEDURE CREATE_EXCEL(P_SQL VARCHAR2, P_PATH VARCHAR2) AS
LANGUAGE JAVA NAME 'CreateExcel.CreateExcel2003(java.lang.String,java.lang.String)';

第一个参数是SQL的字符串,第二个参数是文件路径+文件名称。

这里需要注意一下,单引号里写的是”Java的类名全称.方法名(数据类型,...)”,区分大小写的。

五、调用程序:

输入相应参数:

begin
-- Call the procedure
create_excel(p_sql => 'select * from emp',
p_path => '/share/emp.xls');
end;

程序运行成功!

看看文件目录:

文件已经生成,从服务器下载后,打开看看:

ok~~

假如程序有错误,而且是Java代码的错误,我们怎样获取错误信息呢?这里只需要启用oracle的DBMS_JAVA.SET_OUTPUT();这个过程,

此过程的语法是:

PROCEDURE DBMS_JAVA.SET_OUTPUT(buffersize NUMBER);

具体使用方法:

SQL> SET serveroutput ON size ;
SQL> call dbms_java.set_output();

如果Java代码有问题,我们就可以获得Java的打印信息,包括System.out.println();打印的信息:

oracle PL/SQL调用Java生成Excel的更多相关文章

  1. PL/SQL 调用JAVA使用UDP发送数据

    步骤如下 1.直接在SQL命令中写入JAVA代码(用SYS帐号执行,不然权限等太麻烦) create or replace and resolve java source named udp as i ...

  2. PL/SQL 调用 JAVA代码

    1.直接在 SQL Developer中写入代码 create or replace and compile java source named "HelloWorld" as p ...

  3. ORACLE PL/SQL编程详解

    ORACLE PL/SQL编程详解 编程详解 SQL语言只是访问.操作数据库的语言,并不是一种具有流程控制的程序设计语言,而只有程序设计语言才能用于应用软件的开发.PL /SQL是一种高级数据库程序设 ...

  4. ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!)

    原文:ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!) ORACLE PL/SQL编程之六: 把过程与函数说透(穷追猛打,把根儿都拔起!)   继上篇:ORACLE P ...

  5. ORACLE PL/SQL编程详解(转)

    原帖地址:http://blog.csdn.net/chenjinping123/article/details/8737604 ORACLE PL/SQL编程详解 SQL语言只是访问.操作数据库的语 ...

  6. oracle pl/sql 程序设计 历史笔记整理

    20131016 周三 oracle pl/sql 程序设计 第2章 创建并运行pl/sql代码 sqlplus yjkhecc/yjkhecc@10.85.23.92:1521/orcl 在java ...

  7. Oracle数据库中调用Java类开发存储过程、函数的方法

    Oracle数据库中调用Java类开发存储过程.函数的方法 时间:2014年12月24日  浏览:5538次 oracle数据库的开发非常灵活,不仅支持最基本的SQL,而且还提供了独有的PL/SQL, ...

  8. Oracle触发器反向调用Java程序

    导入jar包 在oracle中导入需要的jar包,我们把编辑好的java类打成jar包,直接在oarcle里面写简单的调用就可以了, 1.操作系统需要拥有支持loadjava命令的jdk. 2.加载j ...

  9. [强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!)

    原文:[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!) [强烈推荐]ORACLE PL/SQL编程详解之七: 程序包的创建与应用(聪明在于学习,天 ...

随机推荐

  1. Java并发编程笔记之LongAdder和LongAccumulator源码探究

    一.LongAdder原理 LongAdder类是JDK1.8新增的一个原子性操作类.AtomicLong通过CAS算法提供了非阻塞的原子性操作,相比受用阻塞算法的同步器来说性能已经很好了,但是JDK ...

  2. Nginx反向代理实现会话(session)保持的两种方式 (转)

    http://blog.csdn.net/gaoqiao1988/article/details/53390352 一.ip_hash: ip_hash使用源地址哈希算法,将同一客户端的请求总是发往同 ...

  3. APS审核经验+审核资料汇总——计算机科学与技术专业上海德语审核

    1.APS是什么 德国驻华使馆文化处留德人员审核部(简称APS)成立于2001年7月,是由德国驻华使馆文化处和德意志学术交流中心(DAAD)在北京共同合作成立的服务机构. APS是中国学生前往德国留学 ...

  4. Java线程池,你了解多少?

    一.前言 随着业务的发展,单线程已经远远不能满足,随即就有多线程的出现.多线程虽然能解决单线程解决不了的事情,但是它也会给你带来额外的问题.比如成千上万甚至上百万的线程时候,你系统就会出现响应延迟.卡 ...

  5. webbrowser在html中写入内容并添加js

    在html中写入内容,并添加js private void btnTestJs_Click(object sender, EventArgs e) { this.webBrowser1.Navigat ...

  6. 以中间件,路由,跨进程事件的姿势使用WebSocket

    通过参考koa中间件,socket.io远程事件调用,以一种新的姿势来使用WebSocket. 浏览器端 浏览器端使用WebSocket很简单 // Create WebSocket connecti ...

  7. java SE 入门之八大内置基本类型(第二篇)

    本文采用eclipse 工具演示,如果您对eclipse 工具不了解,请先学习下 eclipse 工具的使用,这个里面只是简单的介绍下输出和注释: 安装完成eclipse 以后,双击进入 后一次点击 ...

  8. plupload如何删除一条数据

    FilesRemoved用了发现不成功,删除图片这么重要怎能如此 看到老外提的另一个问题发现这个问题解决办法,特此备注以供不会的童鞋参考 uploader.bind('FilesAdded', fun ...

  9. 二:java常用快捷键

    ctrl+F6 切换编辑器 Ctrl+E 快速显示当前Editer的下拉列表 Ctrl+1 快速修复 Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加) Alt+Shif ...

  10. java设计模式-----18、职责链模式

    概念: Chain of Responsibility(CoR)模式也叫职责链模式.责任链模式或者职责连锁模式,是行为模式之一,该模式构造一系列分别担当不同的职责的类的对象来共同完成一个任务,这些类的 ...