Oracle存储过程的分类以及JDBC调用
本文主要是总结 如何实现 JDBC调用Oracle的存储过程,从以下情况分别介绍:
[1]、只有输入IN参数,没有输出OUT参数
[2]、既有输入IN参数,也有输出OUT参数,输出是简单值(非列表)
[3]、既有输入IN参数,也有输出OUT参数,输出是列表
[4]、输入输出参数是同一个(IN OUT)
[5]、存储过程中 使用 truncate 截断表中的数据
【准备工作】
创建一个测试表TMP_MICHAEL ,并插入数据,SQL如下:
Oracle jdbc 常量:
[一]、只有输入IN参数,没有输出OUT参数
调用代码如下:
[二]、既有输入IN参数,也有输出OUT参数,输出是简单值(非列表)
调用程序如下
测试程序就是查询薪水3000以上人员的数量 ,运行结果如下:
------- start 测试调用存储过程:返回值是简单值非列表
符号条件的查询结果 count := 4
------- Test End.
[三]、既有输入IN参数,也有输出OUT参数,输出是列表
首先需要创建PACKAGE TEST_PKG_CURSOR 的SQL如下:
调用存储过程的代码如下:
[四]、输入输出参数是同一个(IN OUT)
调用存储过程的代码:
[五] 存储过程中使用 truncate 清空表中的数据
java 调用
[1]、只有输入IN参数,没有输出OUT参数
[2]、既有输入IN参数,也有输出OUT参数,输出是简单值(非列表)
[3]、既有输入IN参数,也有输出OUT参数,输出是列表
[4]、输入输出参数是同一个(IN OUT)
[5]、存储过程中 使用 truncate 截断表中的数据
【准备工作】
创建一个测试表TMP_MICHAEL ,并插入数据,SQL如下:
- create table TMP_MICHAEL
- (
- USER_ID VARCHAR2(20),
- USER_NAME VARCHAR2(10),
- SALARY NUMBER(8,2),
- OTHER_INFO VARCHAR2(100)
- )
- insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)
- values ('michael', 'Michael', 5000, 'http://sjsky.iteye.com');
- insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)
- values ('zhangsan', '张三', 10000, null);
- insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)
- values ('aoi_sola', '苍井空', 99999.99, 'twitter account');
- insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)
- values ('李四', '李四', 2500, null);
Oracle jdbc 常量:
- private final static String DB_DRIVER = "oracle.jdbc.driver.OracleDriver";
- private final static String DB_CONNECTION = "jdbc:oracle:thin:@127.0.0.1:1521:Ora11g";
- private final static String DB_NAME = "mytest";
- private final static String DB_PWd = "111111";
[一]、只有输入IN参数,没有输出OUT参数
- CREATE OR REPLACE PROCEDURE TEST_MICHAEL_NOOUT(P_USERID IN VARCHAR2,
- P_USERNAME IN VARCHAR2,
- P_SALARY IN NUMBER,
- P_OTHERINFO IN VARCHAR2) IS
- BEGIN
- INSERT INTO TMP_MICHAEL
- (USER_ID, USER_NAME, SALARY, OTHER_INFO)
- VALUES
- (P_USERID, P_USERNAME, P_SALARY, P_OTHERINFO);
- END TEST_MICHAEL_NOOUT;
调用代码如下:
- /**
- * 测试调用存储过程:无返回值
- * @blog http://sjsky.iteye.com
- * @author Michael
- * @throws Exception
- */
- public static void testProcNoOut() throws Exception {
- System.out.println("------- start 测试调用存储过程:无返回值");
- Connection conn = null;
- CallableStatement callStmt = null;
- try {
- Class.forName(DB_DRIVER);
- conn = DriverManager.getConnection(DB_CONNECTION, DB_NAME, DB_PWd);
- // 存储过程 TEST_MICHAEL_NOOUT 其实是向数据库插入一条数据
- callStmt = conn.prepareCall("{call TEST_MICHAEL_NOOUT(?,?,?,?)}");
- // 参数index从1开始,依次 1,2,3...
- callStmt.setString(1, "jdbc");
- callStmt.setString(2, "JDBC");
- callStmt.setDouble(3, 8000.00);
- callStmt.setString(4, "http://sjsky.iteye.com");
- callStmt.execute();
- System.out.println("------- Test End.");
- } catch (Exception e) {
- e.printStackTrace(System.out);
- } finally {
- if (null != callStmt) {
- callStmt.close();
- }
- if (null != conn) {
- conn.close();
- }
- }
- }
[二]、既有输入IN参数,也有输出OUT参数,输出是简单值(非列表)
- CREATE OR REPLACE PROCEDURE TEST_MICHAEL(P_USERID IN VARCHAR2,
- P_SALARY IN NUMBER,
- P_COUNT OUT NUMBER) IS
- V_SALARY NUMBER := P_SALARY;
- BEGIN
- IF V_SALARY IS NULL THEN
- V_SALARY := 0;
- END IF;
- IF P_USERID IS NULL THEN
- SELECT COUNT(*)
- INTO P_COUNT
- FROM TMP_MICHAEL T
- WHERE T.SALARY >= V_SALARY;
- ELSE
- SELECT COUNT(*)
- INTO P_COUNT
- FROM TMP_MICHAEL T
- WHERE T.SALARY >= V_SALARY
- AND T.USER_ID LIKE '%' || P_USERID || '%';
- END IF;
- DBMS_OUTPUT.PUT_LINE('v_count=:' || P_COUNT);
- END TEST_MICHAEL;
调用程序如下
- /**
- * 测试调用存储过程:返回值是简单值非列表
- * @blog http://sjsky.iteye.com
- * @author Michael
- * @throws Exception
- */
- public static void testProcOutSimple() throws Exception {
- System.out.println("------- start 测试调用存储过程:返回值是简单值非列表");
- Connection conn = null;
- CallableStatement stmt = null;
- try {
- Class.forName(DB_DRIVER);
- conn = DriverManager.getConnection(DB_CONNECTION, DB_NAME, DB_PWd);
- stmt = conn.prepareCall("{call TEST_MICHAEL(?,?,?)}");
- stmt.setString(1, "");
- stmt.setDouble(2, 3000);
- // out 注册的index 和取值时要对应
- stmt.registerOutParameter(3, Types.INTEGER);
- stmt.execute();
- // getXxx(index)中的index 需要和上面registerOutParameter的index对应
- int i = stmt.getInt(3);
- System.out.println("符号条件的查询结果 count := " + i);
- System.out.println("------- Test End.");
- } catch (Exception e) {
- e.printStackTrace(System.out);
- } finally {
- if (null != stmt) {
- stmt.close();
- }
- if (null != conn) {
- conn.close();
- }
- }
- }
测试程序就是查询薪水3000以上人员的数量 ,运行结果如下:
------- start 测试调用存储过程:返回值是简单值非列表
符号条件的查询结果 count := 4
------- Test End.
[三]、既有输入IN参数,也有输出OUT参数,输出是列表
首先需要创建PACKAGE TEST_PKG_CURSOR 的SQL如下:
- 首先需要创建PACKAGE TEST_PKG_CURSOR 的SQL如下:
- Sql代码
- CREATE OR REPLACE PACKAGE TEST_PKG_CURSOR IS
- -- Author : MICHAEL http://sjsky.iteye.com
- TYPE TEST_CURSOR IS REF CURSOR;
- END TEST_PKG_CURSOR;
- 再创建存储过程 TEST_P_OUTRS 的SQL如下:
- Sql代码
- CREATE OR REPLACE PROCEDURE TEST_P_OUTRS(P_SALARY IN NUMBER,
- P_OUTRS OUT TEST_PKG_CURSOR.TEST_CURSOR) IS
- V_SALARY NUMBER := P_SALARY;
- BEGIN
- IF P_SALARY IS NULL THEN
- V_SALARY := 0;
- END IF;
- OPEN P_OUTRS FOR
- SELECT * FROM TMP_MICHAEL T WHERE T.SALARY > V_SALARY;
- END TEST_P_OUTRS;
调用存储过程的代码如下:
- /**
- * 测试调用存储过程:有返回值且返回值为列表的
- * @blog http://sjsky.iteye.com
- * @author Michael
- * @throws Exception
- */
- public static void testProcOutRs() throws Exception {
- System.out.println("------- start 测试调用存储过程:有返回值且返回值为列表的");
- Connection conn = null;
- CallableStatement stmt = null;
- ResultSet rs = null;
- try {
- Class.forName(DB_DRIVER);
- conn = DriverManager.getConnection(DB_CONNECTION, DB_NAME, DB_PWd);
- stmt = conn.prepareCall("{call TEST_P_OUTRS(?,?)}");
- stmt.setDouble(1, 3000);
- stmt.registerOutParameter(2, OracleTypes.CURSOR);
- stmt.execute();
- // getXxx(index)中的index 需要和上面registerOutParameter的index对应
- rs = (ResultSet) stmt.getObject(2);
- // 获取列名及类型
- int colunmCount = rs.getMetaData().getColumnCount();
- String[] colNameArr = new String[colunmCount];
- String[] colTypeArr = new String[colunmCount];
- for (int i = 0; i < colunmCount; i++) {
- colNameArr[i] = rs.getMetaData().getColumnName(i + 1);
- colTypeArr[i] = rs.getMetaData().getColumnTypeName(i + 1);
- System.out.print(colNameArr[i] + "(" + colTypeArr[i] + ")"
- + " | ");
- }
- System.out.println();
- while (rs.next()) {
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < colunmCount; i++) {
- sb.append(rs.getString(i + 1) + " | ");
- }
- System.out.println(sb);
- }
- System.out.println("------- Test Proc Out is ResultSet end. ");
- } catch (Exception e) {
- e.printStackTrace(System.out);
- } finally {
- if (null != rs) {
- rs.close();
- }
- if (null != stmt) {
- stmt.close();
- }
- if (null != conn) {
- conn.close();
- }
- }
- }
- 运行结果如下:
- ------- start 测试调用存储过程:有返回值且返回值为列表的
- USER_ID(VARCHAR2) | USER_NAME(VARCHAR2) | SALARY(NUMBER) | OTHER_INFO(VARCHAR2) |
- michael | Michael | 5000 | null |
- zhangsan | 张三 | 10000 | null |
- aoi_sola | 苍井空 | 99999.99 | null |
- jdbc | JDBC | 8000 | http://sjsky.iteye.com |
- ------- Test Proc Out is ResultSet end.
[四]、输入输出参数是同一个(IN OUT)
- CREATE OR REPLACE PROCEDURE TEST_P_INOUT(P_USERID IN VARCHAR2,
- P_NUM IN OUT NUMBER) IS
- V_COUNT NUMBER;
- V_SALARY NUMBER := P_NUM;
- BEGIN
- IF V_SALARY IS NULL THEN
- V_SALARY := 0;
- END IF;
- SELECT COUNT(*)
- INTO V_COUNT
- FROM TMP_MICHAEL
- WHERE USER_ID LIKE '%' || P_USERID || '%'
- AND SALARY >= V_SALARY;
- P_NUM := V_COUNT;
- END TEST_P_INOUT;
调用存储过程的代码:
- /**
- * 测试调用存储过程: INOUT同一个参数:
- * @blog http://sjsky.iteye.com
- * @author Michael
- * @throws Exception
- */
- public static void testProcInOut() throws Exception {
- System.out.println("------- start 测试调用存储过程:INOUT同一个参数");
- Connection conn = null;
- CallableStatement stmt = null;
- try {
- Class.forName(DB_DRIVER);
- conn = DriverManager.getConnection(DB_CONNECTION, DB_NAME, DB_PWd);
- stmt = conn.prepareCall("{call TEST_P_INOUT(?,?)}");
- stmt.setString(1, "michael");
- stmt.setDouble(2, 3000);
- // 注意此次注册out 的index 和上面的in 参数index 相同
- stmt.registerOutParameter(2, Types.INTEGER);
- stmt.execute();
- // getXxx(index)中的index 需要和上面registerOutParameter的index对应
- int count = stmt.getInt(2);
- System.out.println("符号条件的查询结果 count := " + count);
- System.out.println("------- Test End.");
- } catch (Exception e) {
- e.printStackTrace(System.out);
- } finally {
- if (null != stmt) {
- stmt.close();
- }
- if (null != conn) {
- conn.close();
- }
- }
- }
- 运行结果如下:
- ------- start 测试调用存储过程:INOUT同一个参数
- 符号条件的查询结果 count := 1
- ------- Test End.
[五] 存储过程中使用 truncate 清空表中的数据
- create or replace procedure PROC_INSERT_BLDAREN(rownums in number) is
- begin
- EXECUTE IMMEDIATE 'TRUNCATE TABLE BI_BAOLIAO_DAREN';
- insert into BI_BAOLIAO_DAREN (ID,USERID,USERNAME,BAOLIAONUM,CREDITS) select bi_baoliao_sequence.nextval,bl.* from (select b.userid,b.username,count(b.id),sum(b.credits) credits from bi_baoliao b group by b.userid,b.username order by credits desc) bl where rownum <=rownums;
- end PROC_INSERT_BLDAREN;
java 调用
- /**
- * 使用 truncate 先清空表中的数据
- * 然后 插入数据
- */
- public static boolean updateData1(int rownum){
- boolean result=true;
- Connection conn=null;
- CallableStatement cs=null;
- try {
- Date stime=new Date();
- conn=DBConnection.getConnection();
- cs=conn.prepareCall("{call PROC_INSERT_BLDAREN(?)}");
- cs.setInt(1, rownum);
- result=cs.execute();
- Date etime=new Date();
- System.out.println(etime.getTime()-stime.getTime());
- }catch(Exception e){
- e.printStackTrace();
- }finally{
- DBConnection.cleanUp(null, null, cs, null);
- }
- return result;
- }
欢迎访问我的个人公众号,一起交流学习心得,共同进步!